diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c721c1e2ab..5a257f4c85 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,11 +37,12 @@ repos: name: "poetry: check poetry.lock consistency" args: ["--lock"] files: '^(pyproject\.toml|poetry\.lock)$' - # - repo: https://github.com/pycqa/pydocstyle - # rev: 6.1.1 - # hooks: - # - id: pydocstyle - # additional_dependencies: [toml] + - repo: https://github.com/pycqa/pydocstyle + rev: 6.1.1 + hooks: + - id: pydocstyle + additional_dependencies: [toml] + exclude: "^(tests/)|(type_checks/)|(examples/)" - repo: https://github.com/kynan/nbstripout rev: 0.6.1 hooks: diff --git a/doc/source/api/other_types.rst b/doc/source/api/other_types.rst index fcc888fae6..a529ecdb49 100644 --- a/doc/source/api/other_types.rst +++ b/doc/source/api/other_types.rst @@ -16,14 +16,17 @@ Other data types EdgeSetType EdgeSetType ElementalDataType + FeFormat FieldVariable GeometricalRuleType + IgnorableEntity InterpolationOptions LookUpTable3DInterpolationAlgorithm LookUpTableColumnValueType NodalDataType PlyCutoffType PlyType + PuckMaterialType RosetteSelectionMethod SensorType StatusType diff --git a/pyproject.toml b/pyproject.toml index 9185e41256..6f22956be6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -127,7 +127,7 @@ src_paths = ["doc", "src", "tests"] [tool.pydocstyle] convention = "numpy" -add-ignore = "D201,D202,D203,D204" # blank line rules before / after docstring +add-ignore = "D201,D202,D203,D204,D105" # blank line rules before / after docstring; magic methods [tool.codespell] skip = '*.cdb,*.dat' diff --git a/src/ansys/acp/core/__init__.py b/src/ansys/acp/core/__init__.py index fa680fe18d..34eedaad68 100644 --- a/src/ansys/acp/core/__init__.py +++ b/src/ansys/acp/core/__init__.py @@ -1,3 +1,8 @@ +"""PyACP: Ansys Composite PrepPost (ACP) module for Python. + +PyACP enables you to design and analyze layered composite structures. +""" + import importlib.metadata from ._model_printer import get_model_tree, print_model @@ -42,11 +47,13 @@ ElementSetNodalData, Fabric, FabricWithAngle, + FeFormat, FieldVariable, GeometricalRuleType, GeometricalSelectionRule, GeometricalSelectionRuleElementalData, GeometricalSelectionRuleNodalData, + IgnorableEntity, InterpolationOptions, Lamina, LinkedSelectionRule, @@ -76,6 +83,7 @@ ProductionPly, ProductionPlyElementalData, ProductionPlyNodalData, + PuckMaterialType, Rosette, RosetteSelectionMethod, ScalarData, @@ -165,6 +173,7 @@ "ExampleKeys", "Fabric", "FabricWithAngle", + "FeFormat", "FieldVariable", "GeometricalRuleType", "GeometricalSelectionRule", @@ -174,6 +183,7 @@ "get_dpf_unit_system", "get_example_file", "get_model_tree", + "IgnorableEntity", "InterpolationOptions", "Lamina", "launch_acp", @@ -206,6 +216,7 @@ "ProductionPly", "ProductionPlyElementalData", "ProductionPlyNodalData", + "PuckMaterialType", "Rosette", "RosetteSelectionMethod", "ScalarData", diff --git a/src/ansys/acp/core/_model_printer.py b/src/ansys/acp/core/_model_printer.py index 6b58ac8fbf..ba0957e4f6 100644 --- a/src/ansys/acp/core/_model_printer.py +++ b/src/ansys/acp/core/_model_printer.py @@ -50,7 +50,6 @@ def _add_tree_part( def print_model(model: Model) -> None: """Print a tree representation of the model. - Parameters ---------- model: diff --git a/src/ansys/acp/core/_server/acp_instance.py b/src/ansys/acp/core/_server/acp_instance.py index 142cf06e21..10259d0dd8 100644 --- a/src/ansys/acp/core/_server/acp_instance.py +++ b/src/ansys/acp/core/_server/acp_instance.py @@ -165,9 +165,9 @@ def clear(self) -> None: @property def models(self) -> tuple[Model, ...]: - """The models currently loaded on the server. + """Models currently loaded on the server. - Note that the models are returned in arbitrary order. + Note that the models are listed in arbitrary order. """ model_stub = model_pb2_grpc.ObjectServiceStub(self._channel) return tuple( diff --git a/src/ansys/acp/core/_tree_objects/__init__.py b/src/ansys/acp/core/_tree_objects/__init__.py index 140e5cb685..37d9a760ee 100644 --- a/src/ansys/acp/core/_tree_objects/__init__.py +++ b/src/ansys/acp/core/_tree_objects/__init__.py @@ -69,6 +69,7 @@ FieldVariable, InterpolationOptions, Material, + PuckMaterialType, VariableDensity, VariableEngineeringConstants, VariableFabricFiberAngle, @@ -80,7 +81,7 @@ VariableWovenCharacterization, VariableWovenStressLimits, ) -from .model import Model, ModelElementalData, ModelNodalData +from .model import FeFormat, IgnorableEntity, Model, ModelElementalData, ModelNodalData from .modeling_group import ModelingGroup from .modeling_ply import ModelingPly, ModelingPlyElementalData, ModelingPlyNodalData, TaperEdge from .oriented_selection_set import ( @@ -155,11 +156,13 @@ "ElementSetNodalData", "Fabric", "FabricWithAngle", + "FeFormat", "FieldVariable", "GeometricalRuleType", "GeometricalSelectionRule", "GeometricalSelectionRuleElementalData", "GeometricalSelectionRuleNodalData", + "IgnorableEntity", "InterpolationOptions", "Lamina", "LinkedSelectionRule", @@ -172,11 +175,11 @@ "Material", "Model", "ModelElementalData", - "ModelNodalData", "ModelingGroup", "ModelingPly", "ModelingPlyElementalData", "ModelingPlyNodalData", + "ModelNodalData", "NodalDataType", "OrientedSelectionSet", "OrientedSelectionSetElementalData", @@ -189,6 +192,7 @@ "ProductionPly", "ProductionPlyElementalData", "ProductionPlyNodalData", + "PuckMaterialType", "Rosette", "RosetteSelectionMethod", "ScalarData", diff --git a/src/ansys/acp/core/_tree_objects/_grpc_helpers/edge_property_list.py b/src/ansys/acp/core/_tree_objects/_grpc_helpers/edge_property_list.py index 87d2f30064..ea1b8c55b7 100644 --- a/src/ansys/acp/core/_tree_objects/_grpc_helpers/edge_property_list.py +++ b/src/ansys/acp/core/_tree_objects/_grpc_helpers/edge_property_list.py @@ -42,11 +42,10 @@ def _set_callback_apply_changes(self, callback_apply_changes: Callable[[], None] class EdgePropertyList(MutableSequence[ValueT]): - """ - The edge property list is used to wrap graph edges of a specific type. + """Wrap graph edges of a specific type. - For instance FabricWithAngle of a stackup. - This object handles the conversion of the protobuf messages to the + Wraps links between objects of a specific type, for instance FabricWithAngle + of a stackup. This object handles the conversion of the protobuf messages to the corresponding Python object and vice-versa. self._object_list holds the Python object. The python objects are stored to support editing in-place editing. This is achieved by passing a callback @@ -163,42 +162,99 @@ def __contains__(self, item: object) -> bool: return item in self._object_list def append(self, value: ValueT) -> None: + """Append an object to the list. + + Parameters + ---------- + value : + The object to append. + """ obj_list = self._object_list obj_list.append(value) self._set_object_list(obj_list) def count(self, value: ValueT) -> int: + """Count the number of occurrences of an object in the list. + + Parameters + ---------- + value : ValueT + The object to count. + """ return self._object_list.count(value) def index(self, value: ValueT, start: int = 0, stop: int = sys.maxsize) -> int: + """Return the index of the first occurrence of an object in the list. + + Parameters + ---------- + value : + The object to search for. + start : + The index to start searching from. + stop : + The index to stop searching at. + """ return self._object_list.index(value, start, stop) def extend(self, iterable: Iterable[ValueT]) -> None: + """Extend the list by appending all the items from the iterable. + + Parameters + ---------- + iterable : + The iterable to append. + """ obj_list = self._object_list obj_list.extend([it for it in iterable]) self._set_object_list(obj_list) def insert(self, index: int, value: ValueT) -> None: + """Insert an object at a given position. + + Parameters + ---------- + index : + The index to insert at. + value : + The object to insert. + """ obj_list = self._object_list obj_list.insert(index, value) self._set_object_list(obj_list) def pop(self, index: int = -1) -> ValueT: + """Remove and return the object at the given index. + + Parameters + ---------- + index : + The index of the object to remove. + """ obj_list = self._object_list obj = obj_list.pop(index) self._set_object_list(obj_list) return obj def remove(self, value: ValueT) -> None: + """Remove the first occurrence of an object from the list. + + Parameters + ---------- + value : + The object to remove. + """ obj_list = self._object_list obj_list.remove(value) self._set_object_list(obj_list) def reverse(self) -> None: + """Reverse the list in-place.""" self._set_object_list(list(reversed(self._object_list))) def _apply_changes(self) -> None: - """ + """Apply changes to the list. + Use to support in-place modification. This function applies the changes if someone edits one entry of the list. """ @@ -230,6 +286,8 @@ def __repr__(self) -> str: def define_edge_property_list( attribute_name: str, value_type: type[GenericEdgePropertyType], doc: str | None = None ) -> Any: + """Define a list of linked tree objects with link properties.""" + def getter(self: CreatableTreeObject) -> EdgePropertyList[GenericEdgePropertyType]: return EdgePropertyList( parent_object=self, diff --git a/src/ansys/acp/core/_tree_objects/_grpc_helpers/enum_wrapper.py b/src/ansys/acp/core/_tree_objects/_grpc_helpers/enum_wrapper.py index 12af44e38c..cb1afa6a72 100644 --- a/src/ansys/acp/core/_tree_objects/_grpc_helpers/enum_wrapper.py +++ b/src/ansys/acp/core/_tree_objects/_grpc_helpers/enum_wrapper.py @@ -20,6 +20,7 @@ def wrap_to_string_enum( Values of the enum are the keys, converted to lowercase. Returns + ------- : A tuple containing - the string enum diff --git a/src/ansys/acp/core/_tree_objects/_grpc_helpers/linked_object_helpers.py b/src/ansys/acp/core/_tree_objects/_grpc_helpers/linked_object_helpers.py index 215ef00266..24aad8c9f4 100644 --- a/src/ansys/acp/core/_tree_objects/_grpc_helpers/linked_object_helpers.py +++ b/src/ansys/acp/core/_tree_objects/_grpc_helpers/linked_object_helpers.py @@ -18,7 +18,8 @@ def unlink_objects(pb_object: Message) -> None: def linked_path_fields( pb_object: Message, ) -> Iterable[tuple[Message, FieldDescriptor, Union[ResourcePath, CollectionPath]]]: - """ + """Get all linked paths from a protobuf object. + Get tuples (parent_message, field_descriptor, {resource_path or collection_path}) describing all resource or collection paths present in the protobuf object. diff --git a/src/ansys/acp/core/_tree_objects/_grpc_helpers/linked_object_list.py b/src/ansys/acp/core/_tree_objects/_grpc_helpers/linked_object_list.py index 49ff5bc9e6..ba7a2391df 100644 --- a/src/ansys/acp/core/_tree_objects/_grpc_helpers/linked_object_list.py +++ b/src/ansys/acp/core/_tree_objects/_grpc_helpers/linked_object_list.py @@ -21,6 +21,8 @@ class LinkedObjectList(MutableSequence[ValueT]): + """List of linked tree objects.""" + def __init__( self, *, @@ -103,43 +105,104 @@ def __contains__(self, item: object) -> bool: ) def append(self, object: ValueT) -> None: + """Append an object to the list. + + Parameters + ---------- + object: + Object to append. + """ resource_path_list = self._get_resourcepath_list() resource_path_list.append(object._resource_path) self._set_resourcepath_list(resource_path_list) def count(self, value: ValueT) -> int: + """Count the number of occurrences of an object in the list. + + Parameters + ---------- + value: + Object to count. + """ return self._get_resourcepath_list().count(value._resource_path) def index(self, value: ValueT, start: int = 0, stop: int = sys.maxsize) -> int: + """Return the index of the first occurrence of an object in the list. + + Parameters + ---------- + value: + Object to find. + """ return self._get_resourcepath_list().index(value._resource_path, start, stop) def extend(self, iterable: Iterable[ValueT]) -> None: + """Extend the list with an iterable of objects. + + Parameters + ---------- + iterable: + Iterable of objects to append. + """ resource_path_list = self._get_resourcepath_list() resource_path_list.extend([it._resource_path for it in iterable]) self._set_resourcepath_list(resource_path_list) def insert(self, index: int, object: ValueT) -> None: + """Insert an object at a given index. + + Parameters + ---------- + index: + Index to insert at. + object: + Object to insert. + """ resource_path_list = self._get_resourcepath_list() resource_path_list.insert(index, object._resource_path) self._set_resourcepath_list(resource_path_list) def pop(self, index: int = -1) -> ValueT: + """Remove and return an object from the list. + + Parameters + ---------- + index: + Index of the object to be removed. + """ resource_path_list = self._get_resourcepath_list() rp = resource_path_list.pop(index) self._set_resourcepath_list(resource_path_list) return self._object_constructor(rp) def remove(self, value: ValueT) -> None: + """Remove the first occurrence of an object from the list. + + Parameters + ---------- + value: + Object to remove. + """ resource_path_list = self._get_resourcepath_list() resource_path_list.remove(value._resource_path) self._set_resourcepath_list(resource_path_list) def reverse(self) -> None: + """Reverse the list in-place.""" self._set_resourcepath_list(list(reversed(self._get_resourcepath_list()))) def sort( self, *, key: Callable[[ValueT], Any] = lambda obj: obj.name, reverse: bool = False ) -> None: + """Sort the list in-place. + + Parameters + ---------- + key: + Key function to sort by. + reverse: + Whether to sort in reverse order. + """ resource_path_list = self._get_resourcepath_list() evaluated_key_list = [key(self._object_constructor(rp)) for rp in resource_path_list] idx_list = np.argsort(evaluated_key_list) @@ -158,6 +221,8 @@ def __eq__(self, other: Any) -> Any: def define_linked_object_list( attribute_name: str, object_class: type[ChildT], doc: str | None = None ) -> Any: + """Define a list of linked tree objects.""" + def getter(self: ValueT) -> LinkedObjectList[ChildT]: return LinkedObjectList( parent_object=self, @@ -174,6 +239,8 @@ def setter(self: ValueT, value: list[ChildT]) -> None: def define_polymorphic_linked_object_list( attribute_name: str, allowed_types: tuple[Any, ...] ) -> Any: + """Define a list of linked tree objects with polymorphic types.""" + def getter(self: ValueT) -> LinkedObjectList[Any]: return LinkedObjectList( parent_object=self, diff --git a/src/ansys/acp/core/_tree_objects/_grpc_helpers/mapping.py b/src/ansys/acp/core/_tree_objects/_grpc_helpers/mapping.py index cebed0ffe5..70f3645e25 100644 --- a/src/ansys/acp/core/_tree_objects/_grpc_helpers/mapping.py +++ b/src/ansys/acp/core/_tree_objects/_grpc_helpers/mapping.py @@ -22,7 +22,8 @@ class Mapping(Generic[ValueT]): - """ + """Mapping interface for collections of TreeObjects. + Note: We could derive from collections.abc.Mapping to make sure this class conforms to the Mapping interface. """ @@ -71,12 +72,14 @@ def _get_objectinfo_by_id(self, key: str) -> ObjectInfo: # raise NotImplementedError() def values(self) -> Iterator[ValueT]: + """Return an iterator over the values of the mapping.""" return ( self._object_constructor(obj_info, self._channel) for obj_info in self._get_objectinfo_list() ) def items(self) -> Iterator[tuple[str, ValueT]]: + """Return an iterator over the (key, value) pairs of the mapping.""" return ( ( obj_info.info.id, @@ -86,15 +89,19 @@ def items(self) -> Iterator[tuple[str, ValueT]]: ) def keys(self) -> Iterator[str]: + """Return an iterator over the keys of the mapping.""" return iter(self) def __contains__(self, key: str) -> bool: + """Return True if the mapping contains the given key.""" return key in list(self) def __len__(self) -> int: + """Return the number of items in the mapping.""" return len(self._get_objectinfo_list()) def get(self, key: str, default: ValueT | None = None) -> ValueT | None: + """Return the value for key if key is in the mapping, else default.""" try: return self[key] except KeyError: @@ -102,6 +109,8 @@ def get(self, key: str, default: ValueT | None = None) -> ValueT | None: class MutableMapping(Mapping[CreatableValueT]): + """Mutable mapping interface for collections of TreeObjects.""" + def __init__( self, *, @@ -126,6 +135,7 @@ def __delitem__(self, key: str) -> None: ) def clear(self) -> None: + """Remove all items from the mapping.""" for obj_info in self._get_objectinfo_list(): with wrap_grpc_errors(): self._stub.Delete( @@ -135,10 +145,12 @@ def clear(self) -> None: ) def pop(self, key: str) -> CreatableValueT: + """Remove and return the value for key.""" obj_info = self._get_objectinfo_by_id(key) return self._pop_from_info(obj_info) def popitem(self) -> CreatableValueT: + """Remove and return an arbitrary (key, value) pair from the mapping.""" obj_info = self._get_objectinfo_list()[0] return self._pop_from_info(obj_info) @@ -155,6 +167,8 @@ def _pop_from_info(self, object_info: ObjectInfo) -> CreatableValueT: def get_read_only_collection_property( object_class: type[ValueT], stub_class: type[ReadableResourceStub], doc: str | None = None ) -> ReadOnlyProperty[Mapping[ValueT]]: + """Define a read-only mapping of child tree objects.""" + def collection_property(self: ParentT) -> Mapping[ValueT]: return Mapping( channel=self._channel, @@ -177,6 +191,8 @@ def define_create_method( parent_class_name: str, module_name: str, ) -> Callable[Concatenate[ParentT, P], CreatableValueT]: + """Define a create method for child tree objects.""" + def inner(self: ParentT, /, *args: P.args, **kwargs: P.kwargs) -> CreatableValueT: obj = object_class(*args, **kwargs) obj.store(parent=self) @@ -197,6 +213,8 @@ def define_mutable_mapping( stub_class: type[EditableAndReadableResourceStub], doc: str | None = None, ) -> ReadOnlyProperty[MutableMapping[CreatableValueT]]: + """Define a mutable mapping of child tree objects.""" + def collection_property(self: ParentT) -> MutableMapping[CreatableValueT]: return MutableMapping( channel=self._channel, diff --git a/src/ansys/acp/core/_tree_objects/_grpc_helpers/polymorphic_from_pb.py b/src/ansys/acp/core/_tree_objects/_grpc_helpers/polymorphic_from_pb.py index 32c3983cb0..bc1ca1fa56 100644 --- a/src/ansys/acp/core/_tree_objects/_grpc_helpers/polymorphic_from_pb.py +++ b/src/ansys/acp/core/_tree_objects/_grpc_helpers/polymorphic_from_pb.py @@ -11,6 +11,8 @@ class CreatableFromResourcePath(Protocol): + """Interface for objects that can be created from a resource path.""" + @classmethod def _from_resource_path(cls, resource_path: ResourcePath, channel: grpc.Channel) -> Self: ... @@ -21,6 +23,17 @@ def tree_object_from_resource_path( channel: grpc.Channel, allowed_types: tuple[type[CreatableFromResourcePath], ...] | None = None, ) -> CreatableFromResourcePath | None: + """Instantiate a tree object from its resource path. + + Parameters + ---------- + resource_path : + Resource path of the object. + channel : + gRPC channel to the server. + allowed_types : + Allowed types of the object. If None, all registered types are allowed. + """ # Import here to avoid circular references. Cannot use the registry before # all the object have been imported. from ..object_registry import object_registry diff --git a/src/ansys/acp/core/_tree_objects/_grpc_helpers/property_helper.py b/src/ansys/acp/core/_tree_objects/_grpc_helpers/property_helper.py index 8734e05129..8f1594d370 100644 --- a/src/ansys/acp/core/_tree_objects/_grpc_helpers/property_helper.py +++ b/src/ansys/acp/core/_tree_objects/_grpc_helpers/property_helper.py @@ -1,6 +1,7 @@ -""" -Defines helpers for synchronizing object properties with the backend -via gRPC Put / Get calls. +"""Helpers for synchronizing object properties with the backend via gRPC. + +Defines helpers which can be used to define properties which are +automatically synchronized with the backend via gRPC. """ from __future__ import annotations @@ -28,7 +29,8 @@ class _exposed_grpc_property(property): - """ + """Mark a property as exposed via gRPC. + Wrapper around 'property', used to signal that the object should be collected into the '_GRPC_PROPERTIES' class attribute. """ @@ -40,6 +42,11 @@ class _exposed_grpc_property(property): def mark_grpc_properties(cls: T) -> T: + """Class decorator to collect properties marked as exposed via gRPC. + + This decorator should be applied to all classes which define gRPC + properties. + """ props: list[str] = [] # Loop is needed because we otherwise get only the _GRPC_PROPERTIES of one of the base classes. for base_cls in reversed(cls.__bases__): @@ -57,9 +64,7 @@ def mark_grpc_properties(cls: T) -> T: def grpc_linked_object_getter(name: str) -> Callable[[Readable], Any]: - """ - Creates a getter method which obtains the linked server object - """ + """Create a getter method which obtains the linked server object.""" def inner(self: Readable) -> CreatableFromResourcePath | None: # Import here to avoid circular references. Cannot use the registry before @@ -77,9 +82,7 @@ def inner(self: Readable) -> CreatableFromResourcePath | None: def grpc_data_getter( name: str, from_protobuf: _FROM_PROTOBUF_T[_GET_T], check_optional: bool = False ) -> Callable[[Readable], _GET_T]: - """ - Creates a getter method which obtains the server object via the gRPC - Get endpoint. + """Create a getter method which obtains the server object via the gRPC Get endpoint. Parameters ---------- @@ -105,10 +108,7 @@ def inner(self: Readable) -> Any: def grpc_data_setter( name: str, to_protobuf: _TO_PROTOBUF_T[_SET_T] ) -> Callable[[Editable, _SET_T], None]: - """ - Creates a setter method which updates the server object via the gRPC - Put endpoint. - """ + """Create a setter method which updates the server object via the gRPC Put endpoint.""" def inner(self: Editable, value: _SET_T) -> None: self._get_if_stored() @@ -169,7 +169,8 @@ def grpc_data_property( check_optional: bool = False, doc: str | None = None, ) -> ReadWriteProperty[_GET_T, _SET_T]: - """ + """Define a property which is synchronized with the backend via gRPC. + Helper for defining properties accessed via gRPC. The property getter and setter make calls to the gRPC Get and Put endpoints to synchronize the local object with the remote backend. @@ -211,7 +212,8 @@ def grpc_data_property_read_only( check_optional: bool = False, doc: str | None = None, ) -> ReadOnlyProperty[_GET_T]: - """ + """Define a read-only property which is synchronized with the backend via gRPC. + Helper for defining properties accessed via gRPC. The property getter makes call to the gRPC Get endpoints to synchronize the local object with the remote backend. @@ -242,7 +244,8 @@ def grpc_link_property( name: str, doc: str | None = None, ) -> Any: - """ + """Define a gRPC-backed property linking to another object. + Helper for defining linked properties accessed via gRPC. The property getter makes call to the gRPC Get endpoints to get the linked object @@ -268,7 +271,8 @@ def grpc_link_property( def grpc_link_property_read_only(name: str, doc: str | None = None) -> Any: - """ + """Define a read-only gRPC-backed property linking to another object. + Helper for defining linked properties accessed via gRPC. The property getter makes call to the gRPC Get endpoints to get the linked object diff --git a/src/ansys/acp/core/_tree_objects/_grpc_helpers/protocols.py b/src/ansys/acp/core/_tree_objects/_grpc_helpers/protocols.py index c86b4cf88b..8aa62deaf8 100644 --- a/src/ansys/acp/core/_tree_objects/_grpc_helpers/protocols.py +++ b/src/ansys/acp/core/_tree_objects/_grpc_helpers/protocols.py @@ -18,65 +18,111 @@ class CreateRequest(Protocol): + """Interface definition for CreateRequest messages. + + The CreateRequest message is used to create a new object in a collection. + """ + def __init__(self, collection_path: CollectionPath, name: str, properties: Message): ... class ObjectInfo(Protocol): + """Interface definition for ObjectInfo messages. + + The ObjectInfo message contains the full information about an object. + """ + @property def info(self) -> BasicInfo: + """Provide basic information about the object.""" ... @property def properties(self) -> Message: + """Properties of the object.""" ... class ListReply(Protocol): + """Interface definition for ListReply messages. + + The ListReply message contains a list of objects in a collection. + """ + @property def objects(self) -> list[ObjectInfo]: + """List of objects in the collection.""" ... class EditableResourceStub(Protocol): - """Interface definition for ACP Resource service stubs.""" + """Interface definition for ACP Resource service stubs. + + This interface defines the edit methods for ACP Resource service stubs. + """ def Put(self, request: ObjectInfo) -> ObjectInfo: + """RPC method for updating an object.""" ... def Delete(self, request: DeleteRequest) -> Empty: + """RPC method for deleting an object.""" ... class ReadableResourceStub(Protocol): - """Interface definition for ACP Resource service stubs.""" + """Interface definition for ACP Resource service stubs. + + This interface defines the read methods for ACP Resource service stubs. + """ def __init__(self, channel: grpc.Channel): ... def Get(self, request: GetRequest) -> ObjectInfo: + """RPC method for getting an object's information.""" ... def List(self, request: ListRequest) -> ListReply: + """RPC method for listing objects in a collection.""" ... class EditableAndReadableResourceStub(EditableResourceStub, ReadableResourceStub, Protocol): + """Interface definition for ACP Resource service stubs. + + This interface defines the edit and read methods for ACP Resource service stubs. + """ + ... class CreatableResourceStub(Protocol): + """Interface definition for ACP Resource service stubs. + + This interface defines the create methods for ACP Resource service stubs. + """ + def Create(self, request: CreateRequest) -> ObjectInfo: + """RPC method for creating an object.""" ... class CreatableEditableAndReadableResourceStub( CreatableResourceStub, EditableResourceStub, ReadableResourceStub, Protocol ): + """Interface definition for ACP Resource service stubs. + + This interface defines the create, edit, and read methods for ACP Resource service stubs. + """ + ... class GrpcObjectBase(Protocol): + """Interface definition for objects which are backed by a gRPC API.""" + __slots__: Iterable[str] = tuple() _GRPC_PROPERTIES: tuple[str, ...] @@ -100,6 +146,8 @@ def __str__(self) -> str: class Readable(Protocol): + """Interface definition for readable objects.""" + def _get(self) -> None: ... @@ -118,6 +166,8 @@ def _channel(self) -> grpc.Channel: class Editable(Readable, Protocol): + """Interface definition for editable objects.""" + def _put(self) -> None: ... diff --git a/src/ansys/acp/core/_tree_objects/_mesh_data.py b/src/ansys/acp/core/_tree_objects/_mesh_data.py index 9991d90f24..692ea0a81c 100644 --- a/src/ansys/acp/core/_tree_objects/_mesh_data.py +++ b/src/ansys/acp/core/_tree_objects/_mesh_data.py @@ -156,12 +156,12 @@ def __init__( @property def values(self) -> npt.NDArray[ScalarDataT]: - """The values as a numpy array.""" + """Scalar data values as a numpy array.""" return self._values @property def component_name(self) -> str: - """The name of the component.""" + """Name of the component.""" return self._component_name def get_pyvista_mesh( @@ -201,12 +201,12 @@ def __init__( @property def values(self) -> npt.NDArray[np.float64]: - """The values as a numpy array.""" + """Vector data values as a numpy array.""" return self._values @property def component_name(self) -> str: - """The name of the component.""" + """Name of the component.""" return self._component_name def get_pyvista_glyphs( @@ -241,7 +241,7 @@ def get_pyvista_glyphs( def _check_field_type(klass: Any, field_name: str, actual_field_type: str) -> None: - """Checks that the type declared in the dataclass (klass) matches the actual type.""" + """Check that the type declared in the dataclass (klass) matches the actual type.""" declared_field_types: typing.Sequence[str] = cast( typing.Sequence[str], [field.type for field in dataclasses.fields(klass) if field.name == field_name], @@ -265,9 +265,10 @@ class _LabelAndPyvistaFieldNames: @dataclasses.dataclass class MeshDataBase: - """ - Base class for nodal or elemental mesh data. Implements the construction - from a protobuf response and the conversion to a PyVista object. + """Base class for nodal or elemental mesh data. + + Implements the construction from a protobuf response and the conversion + to a PyVista object. """ _LABEL_AND_PYVISTA_FIELD_NAMES: ClassVar[_LabelAndPyvistaFieldNames] @@ -410,7 +411,11 @@ def _mesh_data_property_impl( request_type: type[mesh_query_pb2.GetNodalDataRequest] | type[mesh_query_pb2.GetElementalDataRequest], ) -> ReadOnlyProperty[MeshDataT]: - """Implementation of the mesh data property helpers.""" + """Create a mesh data property. + + Implementation of the mesh data property helpers ``nodal_data_property`` + and ``elemental_data_property``. + """ def getter(self: TreeObject) -> MeshDataT: if not self._is_stored: diff --git a/src/ansys/acp/core/_tree_objects/base.py b/src/ansys/acp/core/_tree_objects/base.py index 6348eb5174..fec927cc6d 100644 --- a/src/ansys/acp/core/_tree_objects/base.py +++ b/src/ansys/acp/core/_tree_objects/base.py @@ -1,7 +1,4 @@ -""" -Defines helpers for synchronizing object properties with the backend -via gRPC Put / Get calls. -""" +"""Base classes for tree objects backed via gRPC API.""" from __future__ import annotations from abc import abstractmethod @@ -42,9 +39,7 @@ @mark_grpc_properties class TreeObjectBase(GrpcObjectBase): - """ - Base class for ACP tree objects. - """ + """Base class for ACP tree objects.""" __slots__: Iterable[str] = ("_channel_store", "_pb_object") @@ -127,11 +122,14 @@ def __repr__(self) -> str: class StubStore(Generic[StubT]): + """Stores a gRPC stub, and creates it on demand.""" + def __init__(self, create_stub_fun: Callable[[], StubT]) -> None: self._stub_store: StubT | None = None self._create_stub_fun = create_stub_fun def get(self, is_stored: bool) -> StubT: + """Get the stored stub, or create it if it does not exist.""" if not is_stored: raise RuntimeError("The server connection is uninitialized.") if self._stub_store is None: @@ -140,6 +138,8 @@ def get(self, is_stored: bool) -> StubT: class TreeObject(TreeObjectBase): + """Base class for ACP objects which can be modified or deleted.""" + __slots__: Iterable[str] = ("_stub_store",) name: ReadWriteProperty[str, str] = grpc_data_property( "info.name", doc="The name of the object." @@ -154,6 +154,7 @@ def __init__(self: TreeObject, name: str = "") -> None: self._stub_store = StubStore(self._create_stub) def delete(self) -> None: + """Delete the object.""" with wrap_grpc_errors(): self._get_stub().Delete( DeleteRequest( @@ -186,6 +187,8 @@ def _get_stub(self) -> EditableAndReadableResourceStub: @mark_grpc_properties class ReadOnlyTreeObject(TreeObjectBase): + """Base class for read-only ACP objects.""" + def __init__(self: ReadOnlyTreeObject) -> None: super().__init__() self._stub_store = StubStore(self._create_stub) @@ -210,6 +213,8 @@ def _get_if_stored(self) -> None: @mark_grpc_properties class CreatableTreeObject(TreeObject): + """Base class for ACP objects which can be created.""" + __slots__: Iterable[str] = tuple() CREATE_REQUEST_TYPE: type[CreateRequest] @@ -217,6 +222,13 @@ def _get_stub(self) -> CreatableEditableAndReadableResourceStub: return cast(CreatableEditableAndReadableResourceStub, super()._get_stub()) def store(self: CreatableTreeObject, parent: TreeObject) -> None: + """Store the object on the server. + + Parameters + ---------- + parent : + Parent object to store the object under. + """ self._channel_store = parent._channel collection_path = CollectionPath( @@ -266,10 +278,7 @@ def __repr__(self) -> str: class TreeObjectAttributeReadOnly(GrpcObjectBase): - """ - Defines an attribute which is defined as a sub-component of a parent - object's protobuf object (read-only). - """ + """Read-only object backed by a sub-component of a parent object's protobuf object.""" __slots__: Iterable[str] = ("_parent_object", "_attribute_path") @@ -313,10 +322,7 @@ def _is_stored(self) -> bool: class PolymorphicMixin(TreeObjectAttributeReadOnly): - """ - Mixin class for attributes which can have multiple types, through a - 'oneof' definition. - """ + """Mixin class for attributes which can have multiple types, through a 'oneof' definition.""" @property def _pb_object_impl(self) -> Any: @@ -328,10 +334,7 @@ def _pb_object_impl(self) -> Any: class TreeObjectAttribute(TreeObjectAttributeReadOnly): - """ - Defines an attribute which is defined as a sub-component of a parent - object's protobuf object (read-write). - """ + """Editable object backed by a sub-component of a parent object's protobuf object.""" __slots__: Iterable[str] = ("_parent_object", "_attribute_path", "_pb_object_store") diff --git a/src/ansys/acp/core/_tree_objects/cad_geometry.py b/src/ansys/acp/core/_tree_objects/cad_geometry.py index bb1902c464..354f4efe85 100644 --- a/src/ansys/acp/core/_tree_objects/cad_geometry.py +++ b/src/ansys/acp/core/_tree_objects/cad_geometry.py @@ -129,7 +129,10 @@ def _create_stub(self) -> cad_geometry_pb2_grpc.ObjectServiceStub: @property def visualization_mesh(self) -> TriangleMesh: - """The CAD Geometry's surface represented as a triangle mesh.""" + """Surface mesh for visualization. + + The CAD Geometry's surface represented as a triangle mesh. + """ if not self._is_stored: raise RuntimeError("Cannot get mesh data from an unstored object") stub = cast(cad_geometry_pb2_grpc.ObjectServiceStub, self._get_stub()) diff --git a/src/ansys/acp/core/_tree_objects/linked_selection_rule.py b/src/ansys/acp/core/_tree_objects/linked_selection_rule.py index c7921c1ade..7abf253901 100644 --- a/src/ansys/acp/core/_tree_objects/linked_selection_rule.py +++ b/src/ansys/acp/core/_tree_objects/linked_selection_rule.py @@ -94,6 +94,7 @@ def __init__( @property def selection_rule(self) -> _LINKABLE_SELECTION_RULE_TYPES: + """Link to an existing selection rule.""" return self._selection_rule @selection_rule.setter @@ -104,6 +105,7 @@ def selection_rule(self, value: _LINKABLE_SELECTION_RULE_TYPES) -> None: @property def operation_type(self) -> BooleanOperationType: + """Operation to combine the selection rule with other selection rules.""" return self._operation_type @operation_type.setter @@ -114,6 +116,7 @@ def operation_type(self, value: BooleanOperationType) -> None: @property def template_rule(self) -> bool: + """Whether the selection rule is a template rule.""" return self._template_rule @template_rule.setter @@ -124,6 +127,7 @@ def template_rule(self, value: bool) -> None: @property def parameter_1(self) -> float: + """First template parameter of the selection rule.""" return self._parameter_1 @parameter_1.setter @@ -134,6 +138,7 @@ def parameter_1(self, value: float) -> None: @property def parameter_2(self) -> float: + """Second template parameter of the selection rule.""" return self._parameter_2 @parameter_2.setter diff --git a/src/ansys/acp/core/_tree_objects/material/__init__.py b/src/ansys/acp/core/_tree_objects/material/__init__.py index 99da429bbf..23a676462f 100644 --- a/src/ansys/acp/core/_tree_objects/material/__init__.py +++ b/src/ansys/acp/core/_tree_objects/material/__init__.py @@ -12,6 +12,7 @@ ConstantWovenStressLimits, FieldVariable, InterpolationOptions, + PuckMaterialType, VariableDensity, VariableEngineeringConstants, VariableFabricFiberAngle, @@ -39,6 +40,7 @@ "InterpolationOptions", "Material", "property_sets", + "PuckMaterialType", "VariableDensity", "VariableEngineeringConstants", "VariableFabricFiberAngle", diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/__init__.py b/src/ansys/acp/core/_tree_objects/material/property_sets/__init__.py index 47c1971ed1..0b6b974c51 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/__init__.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/__init__.py @@ -2,7 +2,7 @@ from .engineering_constants import ConstantEngineeringConstants, VariableEngineeringConstants from .fabric_fiber_angle import ConstantFabricFiberAngle, VariableFabricFiberAngle from .larc_constants import ConstantLaRCConstants, VariableLaRCConstants -from .puck_constants import ConstantPuckConstants, VariablePuckConstants +from .puck_constants import ConstantPuckConstants, PuckMaterialType, VariablePuckConstants from .strain_limits import ConstantStrainLimits, VariableStrainLimits from .stress_limits import ConstantStressLimits, VariableStressLimits from .tsai_wu_constants import ConstantTsaiWuConstants, VariableTsaiWuConstants @@ -13,26 +13,27 @@ __all__ = [ "ConstantDensity", - "VariableDensity", "ConstantEngineeringConstants", - "VariableEngineeringConstants", - "ConstantStressLimits", - "VariableStressLimits", - "ConstantStrainLimits", - "VariableStrainLimits", + "ConstantFabricFiberAngle", + "ConstantLaRCConstants", "ConstantPuckConstants", - "VariablePuckConstants", + "ConstantStrainLimits", + "ConstantStressLimits", + "ConstantTsaiWuConstants", "ConstantWovenCharacterization", - "VariableWovenCharacterization", "ConstantWovenStressLimits", - "VariableWovenStressLimits", - "ConstantTsaiWuConstants", - "VariableTsaiWuConstants", - "ConstantLaRCConstants", - "VariableLaRCConstants", - "ConstantFabricFiberAngle", - "VariableFabricFiberAngle", "FieldVariable", "InterpolationOptions", + "PuckMaterialType", + "VariableDensity", + "VariableEngineeringConstants", + "VariableFabricFiberAngle", + "VariableLaRCConstants", + "VariablePuckConstants", + "VariableStrainLimits", + "VariableStressLimits", + "VariableTsaiWuConstants", + "VariableWovenCharacterization", + "VariableWovenStressLimits", "wrap_property_set", ] diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/density.py b/src/ansys/acp/core/_tree_objects/material/property_sets/density.py index b7d0d5aba8..f93ea3c6df 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/density.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/density.py @@ -6,8 +6,8 @@ from ...base import TreeObject from .base import _ConstantPropertySet, _VariablePropertySet from .property_helper import ( - _constant_material_grpc_data_property, - _variable_material_grpc_data_property, + constant_material_grpc_data_property, + variable_material_grpc_data_property, ) __all__ = ["ConstantDensity", "VariableDensity"] @@ -19,6 +19,8 @@ class _DensityMixin: @mark_grpc_properties class ConstantDensity(_DensityMixin, _ConstantPropertySet): + """Constant density material property set.""" + _GRPC_PROPERTIES = tuple() def __init__( @@ -33,11 +35,13 @@ def __init__( return self.rho = rho - rho = _constant_material_grpc_data_property("rho") + rho = constant_material_grpc_data_property("rho") @mark_grpc_properties class VariableDensity(_DensityMixin, _VariablePropertySet): + """Variable density material property set.""" + _GRPC_PROPERTIES = tuple() - rho = _variable_material_grpc_data_property("rho") + rho = variable_material_grpc_data_property("rho") diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/engineering_constants.py b/src/ansys/acp/core/_tree_objects/material/property_sets/engineering_constants.py index a490d98beb..ea044e3324 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/engineering_constants.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/engineering_constants.py @@ -6,8 +6,8 @@ from ...base import TreeObject from .base import _ConstantPropertySet, _PolymorphicMixin, _VariablePropertySet from .property_helper import ( - _constant_material_grpc_data_property, - _variable_material_grpc_data_property, + constant_material_grpc_data_property, + variable_material_grpc_data_property, ) __all__ = [ @@ -27,6 +27,8 @@ class _EngineeringConstantsMixin(_PolymorphicMixin): @mark_grpc_properties class ConstantEngineeringConstants(_EngineeringConstantsMixin, _ConstantPropertySet): + """Constant engineering constants material property set.""" + _GRPC_PROPERTIES = tuple() def __init__( @@ -57,31 +59,33 @@ def __init__( self.G23 = G23 self.G31 = G31 - E = _constant_material_grpc_data_property("E") - nu = _constant_material_grpc_data_property("nu") - E1 = _constant_material_grpc_data_property("E1") - E2 = _constant_material_grpc_data_property("E2") - E3 = _constant_material_grpc_data_property("E3") - G12 = _constant_material_grpc_data_property("G12") - G23 = _constant_material_grpc_data_property("G23") - G31 = _constant_material_grpc_data_property("G31") - nu12 = _constant_material_grpc_data_property("nu12") - nu23 = _constant_material_grpc_data_property("nu23") - nu13 = _constant_material_grpc_data_property("nu13") + E = constant_material_grpc_data_property("E") + nu = constant_material_grpc_data_property("nu") + E1 = constant_material_grpc_data_property("E1") + E2 = constant_material_grpc_data_property("E2") + E3 = constant_material_grpc_data_property("E3") + G12 = constant_material_grpc_data_property("G12") + G23 = constant_material_grpc_data_property("G23") + G31 = constant_material_grpc_data_property("G31") + nu12 = constant_material_grpc_data_property("nu12") + nu23 = constant_material_grpc_data_property("nu23") + nu13 = constant_material_grpc_data_property("nu13") @mark_grpc_properties class VariableEngineeringConstants(_EngineeringConstantsMixin, _VariablePropertySet): + """Variable engineering constants material property set.""" + _GRPC_PROPERTIES = tuple() - E = _variable_material_grpc_data_property("E") - nu = _variable_material_grpc_data_property("nu") - E1 = _variable_material_grpc_data_property("E1") - E2 = _variable_material_grpc_data_property("E2") - E3 = _variable_material_grpc_data_property("E3") - G12 = _variable_material_grpc_data_property("G12") - G23 = _variable_material_grpc_data_property("G23") - G31 = _variable_material_grpc_data_property("G31") - nu12 = _variable_material_grpc_data_property("nu12") - nu23 = _variable_material_grpc_data_property("nu23") - nu13 = _variable_material_grpc_data_property("nu13") + E = variable_material_grpc_data_property("E") + nu = variable_material_grpc_data_property("nu") + E1 = variable_material_grpc_data_property("E1") + E2 = variable_material_grpc_data_property("E2") + E3 = variable_material_grpc_data_property("E3") + G12 = variable_material_grpc_data_property("G12") + G23 = variable_material_grpc_data_property("G23") + G31 = variable_material_grpc_data_property("G31") + nu12 = variable_material_grpc_data_property("nu12") + nu23 = variable_material_grpc_data_property("nu23") + nu13 = variable_material_grpc_data_property("nu13") diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/fabric_fiber_angle.py b/src/ansys/acp/core/_tree_objects/material/property_sets/fabric_fiber_angle.py index 0e5436b63a..e1d0996107 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/fabric_fiber_angle.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/fabric_fiber_angle.py @@ -6,8 +6,8 @@ from ...base import TreeObject from .base import _ConstantPropertySet, _VariablePropertySet from .property_helper import ( - _constant_material_grpc_data_property, - _variable_material_grpc_data_property, + constant_material_grpc_data_property, + variable_material_grpc_data_property, ) __all__ = ["ConstantFabricFiberAngle", "VariableFabricFiberAngle"] @@ -19,6 +19,12 @@ class _FabricFiberAngleMixin: @mark_grpc_properties class ConstantFabricFiberAngle(_FabricFiberAngleMixin, _ConstantPropertySet): + """Constant fabric fiber angle material property set. + + Defines the rotation angle between the material coordinate system and the fiber direction. + Only used for shear dependent material properties which are provided by Material Designer. + """ + _GRPC_PROPERTIES = tuple() def __init__( @@ -33,11 +39,17 @@ def __init__( return self.fabric_fiber_angle = fabric_fiber_angle - fabric_fiber_angle = _constant_material_grpc_data_property("fabric_fiber_angle") + fabric_fiber_angle = constant_material_grpc_data_property("fabric_fiber_angle") @mark_grpc_properties class VariableFabricFiberAngle(_FabricFiberAngleMixin, _VariablePropertySet): + """Variable fabric fiber angle material property set. + + Defines the rotation angle between the material coordinate system and the fiber direction. + Only used for shear dependent material properties which are provided by Material Designer. + """ + _GRPC_PROPERTIES = tuple() - fabric_fiber_angle = _variable_material_grpc_data_property("fabric_fiber_angle") + fabric_fiber_angle = variable_material_grpc_data_property("fabric_fiber_angle") diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/larc_constants.py b/src/ansys/acp/core/_tree_objects/material/property_sets/larc_constants.py index 9e66407bf9..a5ee08c6ea 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/larc_constants.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/larc_constants.py @@ -6,8 +6,8 @@ from ...base import TreeObject from .base import _ConstantPropertySet, _VariablePropertySet from .property_helper import ( - _constant_material_grpc_data_property, - _variable_material_grpc_data_property, + constant_material_grpc_data_property, + variable_material_grpc_data_property, ) __all__ = ["ConstantLaRCConstants", "VariableLaRCConstants"] @@ -19,6 +19,8 @@ class _LaRCConstantsMixin: @mark_grpc_properties class ConstantLaRCConstants(_LaRCConstantsMixin, _ConstantPropertySet): + """Constant LaRC failure criterion properties.""" + _GRPC_PROPERTIES = tuple() def __init__( @@ -41,23 +43,25 @@ def __init__( self.fracture_toughness_mode_2 = fracture_toughness_mode_2 self.thin_ply_thickness_limit = thin_ply_thickness_limit - fracture_angle_under_compression = _constant_material_grpc_data_property( + fracture_angle_under_compression = constant_material_grpc_data_property( "fracture_angle_under_compression" ) - fracture_toughness_ratio = _constant_material_grpc_data_property("fracture_toughness_ratio") - fracture_toughness_mode_1 = _constant_material_grpc_data_property("fracture_toughness_mode_1") - fracture_toughness_mode_2 = _constant_material_grpc_data_property("fracture_toughness_mode_2") - thin_ply_thickness_limit = _constant_material_grpc_data_property("thin_ply_thickness_limit") + fracture_toughness_ratio = constant_material_grpc_data_property("fracture_toughness_ratio") + fracture_toughness_mode_1 = constant_material_grpc_data_property("fracture_toughness_mode_1") + fracture_toughness_mode_2 = constant_material_grpc_data_property("fracture_toughness_mode_2") + thin_ply_thickness_limit = constant_material_grpc_data_property("thin_ply_thickness_limit") @mark_grpc_properties class VariableLaRCConstants(_LaRCConstantsMixin, _VariablePropertySet): + """Variable LaRC failure criterion properties.""" + _GRPC_PROPERTIES = tuple() - fracture_angle_under_compression = _variable_material_grpc_data_property( + fracture_angle_under_compression = variable_material_grpc_data_property( "fracture_angle_under_compression" ) - fracture_toughness_ratio = _variable_material_grpc_data_property("fracture_toughness_ratio") - fracture_toughness_mode_1 = _variable_material_grpc_data_property("fracture_toughness_mode_1") - fracture_toughness_mode_2 = _variable_material_grpc_data_property("fracture_toughness_mode_2") - thin_ply_thickness_limit = _variable_material_grpc_data_property("thin_ply_thickness_limit") + fracture_toughness_ratio = variable_material_grpc_data_property("fracture_toughness_ratio") + fracture_toughness_mode_1 = variable_material_grpc_data_property("fracture_toughness_mode_1") + fracture_toughness_mode_2 = variable_material_grpc_data_property("fracture_toughness_mode_2") + thin_ply_thickness_limit = variable_material_grpc_data_property("thin_ply_thickness_limit") diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/property_helper.py b/src/ansys/acp/core/_tree_objects/material/property_sets/property_helper.py index 75b25e9ee1..a22fe63238 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/property_helper.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/property_helper.py @@ -2,22 +2,20 @@ from ..._grpc_helpers.property_helper import _exposed_grpc_property, grpc_data_property_read_only -__all__ = ["_variable_material_grpc_data_property", "_constant_material_grpc_data_property"] +__all__ = ["variable_material_grpc_data_property", "constant_material_grpc_data_property"] from ..._grpc_helpers.protocols import Editable, Readable -def _variable_material_grpc_data_property(name: str) -> Any: +def variable_material_grpc_data_property(name: str) -> Any: + """Define a gRPC-backed property for a variable material property set.""" return grpc_data_property_read_only( "values", from_protobuf=lambda values: tuple(getattr(val, name) for val in values) ) def _constant_material_grpc_data_getter(name: str) -> Any: - """ - Creates a getter method which obtains the server object via the gRPC - Get endpoint. - """ + """Create a getter method which obtains the server object via the gRPC Get endpoint.""" def inner(self: Readable) -> Any: self._get_if_stored() @@ -32,10 +30,7 @@ def inner(self: Readable) -> Any: def _constant_material_grpc_data_setter(name: str) -> Any: - """ - Creates a setter method which updates the server object via the gRPC - Put endpoint. - """ + """Create a setter method which updates the server object via the gRPC Put endpoint.""" def inner(self: Editable, value: Any) -> None: self._get_if_stored() @@ -56,7 +51,8 @@ def inner(self: Editable, value: Any) -> None: return inner -def _constant_material_grpc_data_property(name: str) -> Any: +def constant_material_grpc_data_property(name: str) -> Any: + """Define a gRPC-backed property for a constant material property set.""" return _exposed_grpc_property(_constant_material_grpc_data_getter(name=name)).setter( _constant_material_grpc_data_setter(name=name) ) diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/puck_constants.py b/src/ansys/acp/core/_tree_objects/material/property_sets/puck_constants.py index 416bf63b7b..5149dc530d 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/puck_constants.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/puck_constants.py @@ -13,14 +13,16 @@ from ...base import TreeObject from .base import _ConstantPropertySet, _VariablePropertySet from .property_helper import ( - _constant_material_grpc_data_property, - _variable_material_grpc_data_property, + constant_material_grpc_data_property, + variable_material_grpc_data_property, ) -__all__ = ["ConstantPuckConstants", "VariablePuckConstants"] +__all__ = ["ConstantPuckConstants", "VariablePuckConstants", "PuckMaterialType"] class PuckMaterialType(str, Enum): + """Possible Puck material types.""" + IGNORED = "ignored" CARBON = "carbon" GLASS = "glass" @@ -33,6 +35,8 @@ class _PuckConstantsMixin: @mark_grpc_properties class ConstantPuckConstants(_PuckConstantsMixin, _ConstantPropertySet): + """Constant Puck constants material property set.""" + _GRPC_PROPERTIES = tuple() def __init__( @@ -82,13 +86,13 @@ def val_or_default(val: float | None, default: float) -> float: self.M = M self.interface_weakening_factor = interface_weakening_factor - p_21_pos = _constant_material_grpc_data_property("p_21_pos") - p_21_neg = _constant_material_grpc_data_property("p_21_neg") - p_22_pos = _constant_material_grpc_data_property("p_22_pos") - p_22_neg = _constant_material_grpc_data_property("p_22_neg") - s = _constant_material_grpc_data_property("s") - M = _constant_material_grpc_data_property("M") - interface_weakening_factor = _constant_material_grpc_data_property("interface_weakening_factor") + p_21_pos = constant_material_grpc_data_property("p_21_pos") + p_21_neg = constant_material_grpc_data_property("p_21_neg") + p_22_pos = constant_material_grpc_data_property("p_22_pos") + p_22_neg = constant_material_grpc_data_property("p_22_neg") + s = constant_material_grpc_data_property("s") + M = constant_material_grpc_data_property("M") + interface_weakening_factor = constant_material_grpc_data_property("interface_weakening_factor") mat_type: ReadWriteProperty[PuckMaterialType, PuckMaterialType] = grpc_data_property( "mat_type", from_protobuf=PuckMaterialType ) @@ -96,13 +100,15 @@ def val_or_default(val: float | None, default: float) -> float: @mark_grpc_properties class VariablePuckConstants(_PuckConstantsMixin, _VariablePropertySet): + """Variable Puck constants material property set.""" + _GRPC_PROPERTIES = tuple() - p_21_pos = _variable_material_grpc_data_property("p_21_pos") - p_21_neg = _variable_material_grpc_data_property("p_21_neg") - p_22_pos = _variable_material_grpc_data_property("p_22_pos") - p_22_neg = _variable_material_grpc_data_property("p_22_neg") - s = _variable_material_grpc_data_property("s") - M = _variable_material_grpc_data_property("M") - interface_weakening_factor = _variable_material_grpc_data_property("interface_weakening_factor") + p_21_pos = variable_material_grpc_data_property("p_21_pos") + p_21_neg = variable_material_grpc_data_property("p_21_neg") + p_22_pos = variable_material_grpc_data_property("p_22_pos") + p_22_neg = variable_material_grpc_data_property("p_22_neg") + s = variable_material_grpc_data_property("s") + M = variable_material_grpc_data_property("M") + interface_weakening_factor = variable_material_grpc_data_property("interface_weakening_factor") mat_type = grpc_data_property_read_only("mat_type", from_protobuf=PuckMaterialType) diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/strain_limits.py b/src/ansys/acp/core/_tree_objects/material/property_sets/strain_limits.py index 4a1937fd94..46691c790c 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/strain_limits.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/strain_limits.py @@ -6,8 +6,8 @@ from ...base import TreeObject from .base import _ConstantPropertySet, _PolymorphicMixin, _VariablePropertySet from .property_helper import ( - _constant_material_grpc_data_property, - _variable_material_grpc_data_property, + constant_material_grpc_data_property, + variable_material_grpc_data_property, ) __all__ = [ @@ -27,6 +27,8 @@ class _StrainLimitsMixin(_PolymorphicMixin): @mark_grpc_properties class ConstantStrainLimits(_StrainLimitsMixin, _ConstantPropertySet): + """Constant strain limits material property set.""" + _GRPC_PROPERTIES = tuple() def __init__( @@ -57,29 +59,31 @@ def __init__( self.eSyz = eSyz self.eSxz = eSxz - effective_strain = _constant_material_grpc_data_property("effective_strain") - eXc = _constant_material_grpc_data_property("eXc") - eYc = _constant_material_grpc_data_property("eYc") - eZc = _constant_material_grpc_data_property("eZc") - eXt = _constant_material_grpc_data_property("eXt") - eYt = _constant_material_grpc_data_property("eYt") - eZt = _constant_material_grpc_data_property("eZt") - eSxy = _constant_material_grpc_data_property("eSxy") - eSyz = _constant_material_grpc_data_property("eSyz") - eSxz = _constant_material_grpc_data_property("eSxz") + effective_strain = constant_material_grpc_data_property("effective_strain") + eXc = constant_material_grpc_data_property("eXc") + eYc = constant_material_grpc_data_property("eYc") + eZc = constant_material_grpc_data_property("eZc") + eXt = constant_material_grpc_data_property("eXt") + eYt = constant_material_grpc_data_property("eYt") + eZt = constant_material_grpc_data_property("eZt") + eSxy = constant_material_grpc_data_property("eSxy") + eSyz = constant_material_grpc_data_property("eSyz") + eSxz = constant_material_grpc_data_property("eSxz") @mark_grpc_properties class VariableStrainLimits(_StrainLimitsMixin, _VariablePropertySet): + """Variable strain limits material property set.""" + _GRPC_PROPERTIES = tuple() - effective_strain = _variable_material_grpc_data_property("effective_strain") - eXc = _variable_material_grpc_data_property("eXc") - eYc = _variable_material_grpc_data_property("eYc") - eZc = _variable_material_grpc_data_property("eZc") - eXt = _variable_material_grpc_data_property("eXt") - eYt = _variable_material_grpc_data_property("eYt") - eZt = _variable_material_grpc_data_property("eZt") - eSxy = _variable_material_grpc_data_property("eSxy") - eSyz = _variable_material_grpc_data_property("eSyz") - eSxz = _variable_material_grpc_data_property("eSxz") + effective_strain = variable_material_grpc_data_property("effective_strain") + eXc = variable_material_grpc_data_property("eXc") + eYc = variable_material_grpc_data_property("eYc") + eZc = variable_material_grpc_data_property("eZc") + eXt = variable_material_grpc_data_property("eXt") + eYt = variable_material_grpc_data_property("eYt") + eZt = variable_material_grpc_data_property("eZt") + eSxy = variable_material_grpc_data_property("eSxy") + eSyz = variable_material_grpc_data_property("eSyz") + eSxz = variable_material_grpc_data_property("eSxz") diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/stress_limits.py b/src/ansys/acp/core/_tree_objects/material/property_sets/stress_limits.py index 38feabe38c..d3112eda91 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/stress_limits.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/stress_limits.py @@ -6,8 +6,8 @@ from ...base import TreeObject from .base import _ConstantPropertySet, _PolymorphicMixin, _VariablePropertySet from .property_helper import ( - _constant_material_grpc_data_property, - _variable_material_grpc_data_property, + constant_material_grpc_data_property, + variable_material_grpc_data_property, ) __all__ = [ @@ -27,6 +27,8 @@ class _StressLimitsMixin(_PolymorphicMixin): @mark_grpc_properties class ConstantStressLimits(_StressLimitsMixin, _ConstantPropertySet): + """Constant stress limits material property set.""" + _GRPC_PROPERTIES = tuple() def __init__( @@ -57,29 +59,31 @@ def __init__( self.Syz = Syz self.Sxz = Sxz - effective_stress = _constant_material_grpc_data_property("effective_stress") - Xc = _constant_material_grpc_data_property("Xc") - Yc = _constant_material_grpc_data_property("Yc") - Zc = _constant_material_grpc_data_property("Zc") - Xt = _constant_material_grpc_data_property("Xt") - Yt = _constant_material_grpc_data_property("Yt") - Zt = _constant_material_grpc_data_property("Zt") - Sxy = _constant_material_grpc_data_property("Sxy") - Syz = _constant_material_grpc_data_property("Syz") - Sxz = _constant_material_grpc_data_property("Sxz") + effective_stress = constant_material_grpc_data_property("effective_stress") + Xc = constant_material_grpc_data_property("Xc") + Yc = constant_material_grpc_data_property("Yc") + Zc = constant_material_grpc_data_property("Zc") + Xt = constant_material_grpc_data_property("Xt") + Yt = constant_material_grpc_data_property("Yt") + Zt = constant_material_grpc_data_property("Zt") + Sxy = constant_material_grpc_data_property("Sxy") + Syz = constant_material_grpc_data_property("Syz") + Sxz = constant_material_grpc_data_property("Sxz") @mark_grpc_properties class VariableStressLimits(_StressLimitsMixin, _VariablePropertySet): + """Variable stress limits material property set.""" + _GRPC_PROPERTIES = tuple() - effective_stress = _variable_material_grpc_data_property("effective_stress") - Xc = _variable_material_grpc_data_property("Xc") - Yc = _variable_material_grpc_data_property("Yc") - Zc = _variable_material_grpc_data_property("Zc") - Xt = _variable_material_grpc_data_property("Xt") - Yt = _variable_material_grpc_data_property("Yt") - Zt = _variable_material_grpc_data_property("Zt") - Sxy = _variable_material_grpc_data_property("Sxy") - Syz = _variable_material_grpc_data_property("Syz") - Sxz = _variable_material_grpc_data_property("Sxz") + effective_stress = variable_material_grpc_data_property("effective_stress") + Xc = variable_material_grpc_data_property("Xc") + Yc = variable_material_grpc_data_property("Yc") + Zc = variable_material_grpc_data_property("Zc") + Xt = variable_material_grpc_data_property("Xt") + Yt = variable_material_grpc_data_property("Yt") + Zt = variable_material_grpc_data_property("Zt") + Sxy = variable_material_grpc_data_property("Sxy") + Syz = variable_material_grpc_data_property("Syz") + Sxz = variable_material_grpc_data_property("Sxz") diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/tsai_wu_constants.py b/src/ansys/acp/core/_tree_objects/material/property_sets/tsai_wu_constants.py index 7f79220e89..84435238ea 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/tsai_wu_constants.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/tsai_wu_constants.py @@ -6,8 +6,8 @@ from ...base import TreeObject from .base import _ConstantPropertySet, _VariablePropertySet from .property_helper import ( - _constant_material_grpc_data_property, - _variable_material_grpc_data_property, + constant_material_grpc_data_property, + variable_material_grpc_data_property, ) __all__ = ["ConstantTsaiWuConstants", "VariableTsaiWuConstants"] @@ -19,6 +19,8 @@ class _TsaiWuConstantsMixin: @mark_grpc_properties class ConstantTsaiWuConstants(_TsaiWuConstantsMixin, _ConstantPropertySet): + """Constant Tsai-Wu constants material property set.""" + _GRPC_PROPERTIES = tuple() def __init__( @@ -37,15 +39,17 @@ def __init__( self.XZ = XZ self.YZ = YZ - XY = _constant_material_grpc_data_property("XY") - XZ = _constant_material_grpc_data_property("XZ") - YZ = _constant_material_grpc_data_property("YZ") + XY = constant_material_grpc_data_property("XY") + XZ = constant_material_grpc_data_property("XZ") + YZ = constant_material_grpc_data_property("YZ") @mark_grpc_properties class VariableTsaiWuConstants(_TsaiWuConstantsMixin, _VariablePropertySet): + """Variable Tsai-Wu constants material property set.""" + _GRPC_PROPERTIES = tuple() - XY = _variable_material_grpc_data_property("XY") - XZ = _variable_material_grpc_data_property("XZ") - YZ = _variable_material_grpc_data_property("YZ") + XY = variable_material_grpc_data_property("XY") + XZ = variable_material_grpc_data_property("XZ") + YZ = variable_material_grpc_data_property("YZ") diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/woven_characterization.py b/src/ansys/acp/core/_tree_objects/material/property_sets/woven_characterization.py index 463500bdb5..550cf06c77 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/woven_characterization.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/woven_characterization.py @@ -6,8 +6,8 @@ from ...base import TreeObject from .base import _ConstantPropertySet, _VariablePropertySet from .property_helper import ( - _constant_material_grpc_data_property, - _variable_material_grpc_data_property, + constant_material_grpc_data_property, + variable_material_grpc_data_property, ) __all__ = ["ConstantWovenCharacterization", "VariableWovenCharacterization"] @@ -19,6 +19,8 @@ class _WovenCharacterizationMixin: @mark_grpc_properties class ConstantWovenCharacterization(_WovenCharacterizationMixin, _ConstantPropertySet): + """Constant woven characterization material property set.""" + _GRPC_PROPERTIES = tuple() def __init__( @@ -55,32 +57,34 @@ def __init__( self.G23_2 = G23_2 self.nu12_2 = nu12_2 - orientation_1 = _constant_material_grpc_data_property("orientation_1") - E1_1 = _constant_material_grpc_data_property("E1_1") - E2_1 = _constant_material_grpc_data_property("E2_1") - G12_1 = _constant_material_grpc_data_property("G12_1") - G23_1 = _constant_material_grpc_data_property("G23_1") - nu12_1 = _constant_material_grpc_data_property("nu12_1") - orientation_2 = _constant_material_grpc_data_property("orientation_2") - E1_2 = _constant_material_grpc_data_property("E1_2") - E2_2 = _constant_material_grpc_data_property("E2_2") - G12_2 = _constant_material_grpc_data_property("G12_2") - G23_2 = _constant_material_grpc_data_property("G23_2") - nu12_2 = _constant_material_grpc_data_property("nu12_2") + orientation_1 = constant_material_grpc_data_property("orientation_1") + E1_1 = constant_material_grpc_data_property("E1_1") + E2_1 = constant_material_grpc_data_property("E2_1") + G12_1 = constant_material_grpc_data_property("G12_1") + G23_1 = constant_material_grpc_data_property("G23_1") + nu12_1 = constant_material_grpc_data_property("nu12_1") + orientation_2 = constant_material_grpc_data_property("orientation_2") + E1_2 = constant_material_grpc_data_property("E1_2") + E2_2 = constant_material_grpc_data_property("E2_2") + G12_2 = constant_material_grpc_data_property("G12_2") + G23_2 = constant_material_grpc_data_property("G23_2") + nu12_2 = constant_material_grpc_data_property("nu12_2") @mark_grpc_properties class VariableWovenCharacterization(_WovenCharacterizationMixin, _VariablePropertySet): + """Variable woven characterization material property set.""" + _GRPC_PROPERTIES = tuple() - E1_1 = _variable_material_grpc_data_property("E1_1") - E2_1 = _variable_material_grpc_data_property("E2_1") - G12_1 = _variable_material_grpc_data_property("G12_1") - G23_1 = _variable_material_grpc_data_property("G23_1") - nu12_1 = _variable_material_grpc_data_property("nu12_1") - orientation_2 = _variable_material_grpc_data_property("orientation_2") - E1_2 = _variable_material_grpc_data_property("E1_2") - E2_2 = _variable_material_grpc_data_property("E2_2") - G12_2 = _variable_material_grpc_data_property("G12_2") - G23_2 = _variable_material_grpc_data_property("G23_2") - nu12_2 = _variable_material_grpc_data_property("nu12_2") + E1_1 = variable_material_grpc_data_property("E1_1") + E2_1 = variable_material_grpc_data_property("E2_1") + G12_1 = variable_material_grpc_data_property("G12_1") + G23_1 = variable_material_grpc_data_property("G23_1") + nu12_1 = variable_material_grpc_data_property("nu12_1") + orientation_2 = variable_material_grpc_data_property("orientation_2") + E1_2 = variable_material_grpc_data_property("E1_2") + E2_2 = variable_material_grpc_data_property("E2_2") + G12_2 = variable_material_grpc_data_property("G12_2") + G23_2 = variable_material_grpc_data_property("G23_2") + nu12_2 = variable_material_grpc_data_property("nu12_2") diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/woven_stress_limits.py b/src/ansys/acp/core/_tree_objects/material/property_sets/woven_stress_limits.py index 75e3ab2ee7..17afb6b7c0 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/woven_stress_limits.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/woven_stress_limits.py @@ -6,8 +6,8 @@ from ...base import TreeObject from .base import _ConstantPropertySet, _VariablePropertySet from .property_helper import ( - _constant_material_grpc_data_property, - _variable_material_grpc_data_property, + constant_material_grpc_data_property, + variable_material_grpc_data_property, ) __all__ = ["ConstantWovenStressLimits", "VariableWovenStressLimits"] @@ -19,6 +19,8 @@ class _WovenStressLimitsMixin: @mark_grpc_properties class ConstantWovenStressLimits(_WovenStressLimitsMixin, _ConstantPropertySet): + """Constant stress limits property set for woven materials.""" + _GRPC_PROPERTIES = tuple() def __init__( @@ -49,27 +51,29 @@ def __init__( self.Syz = Syz self.Sxz = Sxz - Xc = _constant_material_grpc_data_property("Xc") - Yc = _constant_material_grpc_data_property("Yc") - Zc = _constant_material_grpc_data_property("Zc") - Xt = _constant_material_grpc_data_property("Xt") - Yt = _constant_material_grpc_data_property("Yt") - Zt = _constant_material_grpc_data_property("Zt") - Sxy = _constant_material_grpc_data_property("Sxy") - Syz = _constant_material_grpc_data_property("Syz") - Sxz = _constant_material_grpc_data_property("Sxz") + Xc = constant_material_grpc_data_property("Xc") + Yc = constant_material_grpc_data_property("Yc") + Zc = constant_material_grpc_data_property("Zc") + Xt = constant_material_grpc_data_property("Xt") + Yt = constant_material_grpc_data_property("Yt") + Zt = constant_material_grpc_data_property("Zt") + Sxy = constant_material_grpc_data_property("Sxy") + Syz = constant_material_grpc_data_property("Syz") + Sxz = constant_material_grpc_data_property("Sxz") @mark_grpc_properties class VariableWovenStressLimits(_WovenStressLimitsMixin, _VariablePropertySet): + """Variable stress limits property set for woven materials.""" + _GRPC_PROPERTIES = tuple() - Xc = _variable_material_grpc_data_property("Xc") - Yc = _variable_material_grpc_data_property("Yc") - Zc = _variable_material_grpc_data_property("Zc") - Xt = _variable_material_grpc_data_property("Xt") - Yt = _variable_material_grpc_data_property("Yt") - Zt = _variable_material_grpc_data_property("Zt") - Sxy = _variable_material_grpc_data_property("Sxy") - Syz = _variable_material_grpc_data_property("Syz") - Sxz = _variable_material_grpc_data_property("Sxz") + Xc = variable_material_grpc_data_property("Xc") + Yc = variable_material_grpc_data_property("Yc") + Zc = variable_material_grpc_data_property("Zc") + Xt = variable_material_grpc_data_property("Xt") + Yt = variable_material_grpc_data_property("Yt") + Zt = variable_material_grpc_data_property("Zt") + Sxy = variable_material_grpc_data_property("Sxy") + Syz = variable_material_grpc_data_property("Syz") + Sxz = variable_material_grpc_data_property("Sxz") diff --git a/src/ansys/acp/core/_tree_objects/material/property_sets/wrapper.py b/src/ansys/acp/core/_tree_objects/material/property_sets/wrapper.py index f910af7c9b..fba1b19de9 100644 --- a/src/ansys/acp/core/_tree_objects/material/property_sets/wrapper.py +++ b/src/ansys/acp/core/_tree_objects/material/property_sets/wrapper.py @@ -1,4 +1,5 @@ -""" +"""Helpers for defining material property sets. + Implements a helper function ``wrap_property_set`` to expose property sets on the Material, as a property. """ @@ -92,7 +93,7 @@ def inner(self: Any) -> None: def wrap_property_set(name: str, type_constant: type[TC], type_variable: type[TV]) -> Any: - """Helper function to define a material property set on the material. + """Define a material property set on the material. Expose a property set on the ``Material``, as a property. The property automatically chooses the appropriate type (``type_constant`` or ``type_variable``), diff --git a/src/ansys/acp/core/_tree_objects/model.py b/src/ansys/acp/core/_tree_objects/model.py index a4f9df6be4..cad9458089 100644 --- a/src/ansys/acp/core/_tree_objects/model.py +++ b/src/ansys/acp/core/_tree_objects/model.py @@ -87,17 +87,24 @@ from .variable_offset_selection_rule import VariableOffsetSelectionRule from .virtual_geometry import VirtualGeometry -__all__ = ["MeshData", "Model", "ModelElementalData", "ModelNodalData"] - -_FeFormat, _fe_format_to_pb, _ = wrap_to_string_enum( - "_FeFormat", +__all__ = [ + "MeshData", + "Model", + "ModelElementalData", + "ModelNodalData", + "FeFormat", + "IgnorableEntity", +] + +FeFormat, fe_format_to_pb, _ = wrap_to_string_enum( + "FeFormat", model_pb2.Format, module=__name__, value_converter=lambda val: val.lower().replace("_", ":"), doc="Options for the format of the FE file.", ) -_IgnorableEntity, _ignorable_entity_to_pb, _ = wrap_to_string_enum( - "_IgnorableEntity", +IgnorableEntity, ignorable_entity_to_pb, _ = wrap_to_string_enum( + "IgnorableEntity", model_pb2.LoadFromFEFileRequest.IgnorableEntity, module=__name__, doc="Options for the entities to ignore when loading an FE file.", @@ -116,6 +123,7 @@ class MeshData: element_nodes_offsets: npt.NDArray[np.int32] def to_pyvista(self) -> UnstructuredGrid: + """Convert the mesh data to a PyVista mesh.""" return UnstructuredGrid( to_pyvista_faces( element_types=self.element_types, @@ -222,6 +230,15 @@ def _create_stub(self) -> model_pb2_grpc.ObjectServiceStub: @classmethod def from_file(cls, *, path: _PATH, channel: Channel) -> Model: + """Instantiate a Model from an ACPH5 file. + + Parameters + ---------- + path: + File path, on the server. + channel: + gRPC channel to the server. + """ # Send absolute paths to the server, since its CWD may not match # the Python CWD. request = model_pb2.LoadFromFileRequest(path=path_to_str_checked(path)) @@ -235,13 +252,36 @@ def from_fe_file( *, path: _PATH, channel: Channel, - format: _FeFormat, # type: ignore - ignored_entities: Iterable[_IgnorableEntity] = (), # type: ignore + format: FeFormat, # type: ignore + ignored_entities: Iterable[IgnorableEntity] = (), # type: ignore convert_section_data: bool = False, unit_system: UnitSystemType = UnitSystemType.UNDEFINED, ) -> Model: - format_pb = _fe_format_to_pb(format) - ignored_entities_pb = [_ignorable_entity_to_pb(val) for val in ignored_entities] + """Load the model from an FE file. + + Parameters + ---------- + path: + File path, on the server. + channel: + gRPC channel to the server. + format: + Format of the FE file. Can be one of ``"ansys:h5"``, ``"ansys:cdb"``, + ``"ansys:dat"``, ``"abaqus:inp"``, or ``"nastran:bdf"``. + ignored_entities: + Entities to ignore when loading the FE file. Can be a subset of + the following values: + ``"coordinate_systems"``, ``"element_sets"``, ``"materials"``, + ``"mesh"``, or ``"shell_sections"``. + convert_section_data: + Whether to import the section data of a shell model and convert it + into ACP composite definitions. + unit_system: + Set the unit system of the model to the given value. Ignored + if the unit system is already set in the FE file. + """ + format_pb = fe_format_to_pb(format) + ignored_entities_pb = [ignorable_entity_to_pb(val) for val in ignored_entities] request = model_pb2.LoadFromFEFileRequest( path=path_to_str_checked(path), @@ -255,6 +295,13 @@ def from_fe_file( return cls._from_object_info(object_info=reply, channel=channel) def update(self, *, relations_only: bool = False) -> None: + """Update the model. + + Parameters + ---------- + relations_only : + Whether to update and propagate only the status of all objects. + """ with wrap_grpc_errors(): self._get_stub().Update( model_pb2.UpdateRequest( @@ -283,6 +330,13 @@ def save(self, path: _PATH, *, save_cache: bool = True) -> None: ) def save_analysis_model(self, path: _PATH) -> None: + """Save the analysis model to a CDB file. + + Parameters + ---------- + path: + Target file path. E.g. /tmp/ACPAnalysisModel.cdb + """ with wrap_grpc_errors(): self._get_stub().SaveAnalysisModel( model_pb2.SaveAnalysisModelRequest( @@ -517,6 +571,7 @@ def export_materials(self, path: _PATH) -> None: @property def mesh(self) -> MeshData: + """Mesh on which the model is defined.""" mesh_query_stub = mesh_query_pb2_grpc.MeshQueryServiceStub(self._channel) reply = mesh_query_stub.GetMeshData(base_pb2.GetRequest(resource_path=self._resource_path)) return MeshData( diff --git a/src/ansys/acp/core/_tree_objects/modeling_group.py b/src/ansys/acp/core/_tree_objects/modeling_group.py index c6c224b072..28be093f6d 100644 --- a/src/ansys/acp/core/_tree_objects/modeling_group.py +++ b/src/ansys/acp/core/_tree_objects/modeling_group.py @@ -2,7 +2,6 @@ from collections.abc import Iterable import dataclasses -from typing import Any from ansys.api.acp.v0 import modeling_group_pb2, modeling_group_pb2_grpc, modeling_ply_pb2_grpc @@ -37,18 +36,23 @@ class ModelingGroupNodalData(NodalData): @mark_grpc_properties @register class ModelingGroup(CreatableTreeObject, IdTreeObject): + """Instantiate a modeling group. + + Parameters + ---------- + name + Name of the modeling group. + """ + __slots__: Iterable[str] = tuple() _COLLECTION_LABEL = "modeling_groups" OBJECT_INFO_TYPE = modeling_group_pb2.ObjectInfo CREATE_REQUEST_TYPE = modeling_group_pb2.CreateRequest - def __init__(self, name: str = "ModelingGroup", **kwargs: Any): + def __init__(self, *, name: str = "ModelingGroup"): super().__init__(name=name) - for key, value in kwargs.items(): - setattr(self, key, value) - def _create_stub(self) -> modeling_group_pb2_grpc.ObjectServiceStub: return modeling_group_pb2_grpc.ObjectServiceStub(self._channel) diff --git a/src/ansys/acp/core/_tree_objects/modeling_ply.py b/src/ansys/acp/core/_tree_objects/modeling_ply.py index 16a464c905..394f522423 100644 --- a/src/ansys/acp/core/_tree_objects/modeling_ply.py +++ b/src/ansys/acp/core/_tree_objects/modeling_ply.py @@ -109,6 +109,7 @@ def __init__(self, edge_set: EdgeSet, angle: float, offset: float): @property def edge_set(self) -> EdgeSet: + """Edge along which the ply tapering is applied.""" return self._edge_set @edge_set.setter @@ -119,6 +120,7 @@ def edge_set(self, edge_set: EdgeSet) -> None: @property def angle(self) -> float: + """Angle between the cutting plane and the reference surface.""" return self._angle @angle.setter @@ -129,6 +131,11 @@ def angle(self, angle: float) -> None: @property def offset(self) -> float: + """Move the cutting plane along the out-of-plane direction. + + A negative value cuts the elements at the edge where the in-plane + offset is ``-offset/tan(angle)``. + """ return self._offset @offset.setter diff --git a/src/ansys/acp/core/_tree_objects/object_registry.py b/src/ansys/acp/core/_tree_objects/object_registry.py index 97bde2a526..bd19fbe4b6 100644 --- a/src/ansys/acp/core/_tree_objects/object_registry.py +++ b/src/ansys/acp/core/_tree_objects/object_registry.py @@ -8,5 +8,10 @@ def register(cls: T) -> T: + """Class decorator for ACP tree objects. + + Registers the tree object, enabling it to be instantiated polymorphically + from a resource path. + """ object_registry[cls._COLLECTION_LABEL] = cls return cls diff --git a/src/ansys/acp/core/_tree_objects/stackup.py b/src/ansys/acp/core/_tree_objects/stackup.py index 3ccb0bb198..d77c378276 100644 --- a/src/ansys/acp/core/_tree_objects/stackup.py +++ b/src/ansys/acp/core/_tree_objects/stackup.py @@ -56,6 +56,7 @@ def __init__(self, fabric: Fabric, angle: float = 0.0): @property def fabric(self) -> Fabric: + """Linked fabric.""" return self._fabric @fabric.setter @@ -66,6 +67,7 @@ def fabric(self, value: Fabric) -> None: @property def angle(self) -> float: + """Orientation angle in degree of the fabric with respect to the reference direction.""" return self._angle @angle.setter diff --git a/src/ansys/acp/core/_tree_objects/sublaminate.py b/src/ansys/acp/core/_tree_objects/sublaminate.py index 54461a5796..361b46e81d 100644 --- a/src/ansys/acp/core/_tree_objects/sublaminate.py +++ b/src/ansys/acp/core/_tree_objects/sublaminate.py @@ -45,6 +45,7 @@ def __init__(self, material: _LINKABLE_MATERIAL_TYPES, angle: float = 0.0): @property def material(self) -> _LINKABLE_MATERIAL_TYPES: + """Link to an existing fabric or stackup.""" return self._material @material.setter @@ -55,6 +56,7 @@ def material(self, value: _LINKABLE_MATERIAL_TYPES) -> None: @property def angle(self) -> float: + """Orientation angle in degree of the material with respect to the reference direction.""" return self._angle @angle.setter diff --git a/src/ansys/acp/core/_tree_objects/virtual_geometry.py b/src/ansys/acp/core/_tree_objects/virtual_geometry.py index 7cf01602de..100350cf7b 100644 --- a/src/ansys/acp/core/_tree_objects/virtual_geometry.py +++ b/src/ansys/acp/core/_tree_objects/virtual_geometry.py @@ -27,6 +27,7 @@ def __init__(self, cad_geometry: CADGeometry, path: str): @property def cad_geometry(self) -> CADGeometry: + """Linked CAD geometry.""" return self._cad_geometry @cad_geometry.setter @@ -37,6 +38,7 @@ def cad_geometry(self, value: CADGeometry) -> None: @property def path(self) -> str: + """Topological path of the sub-shape within the CAD geometry.""" return self._path @path.setter diff --git a/src/ansys/acp/core/_utils/array_conversions.py b/src/ansys/acp/core/_utils/array_conversions.py index 1dc807e096..6735341773 100644 --- a/src/ansys/acp/core/_utils/array_conversions.py +++ b/src/ansys/acp/core/_utils/array_conversions.py @@ -9,20 +9,24 @@ def to_1D_double_array(data: Collection[float]) -> DoubleArray: + """Convert a 1D collection of floats to a DoubleArray protobuf message.""" return DoubleArray(shape=[len(data)], data=tuple(data)) def to_1D_int_array(data: Collection[int]) -> IntArray: + """Convert a 1D collection of ints to a IntArray protobuf message.""" return IntArray(shape=[len(data)], data=tuple(data)) def to_tuple_from_1D_array(array: Union[IntArray, DoubleArray]) -> tuple[Any, ...]: + """Convert a 1D IntArray or DoubleArray protobuf message to a tuple.""" if not len(array.shape) == 1: raise RuntimeError(f"Cannot convert {len(array.shape)}-dimensional array to tuple!") return tuple(array.data) def to_ND_double_array_from_numpy(data: npt.NDArray[np.float64]) -> DoubleArray: + """Convert a numpy array to a DoubleArray protobuf message.""" return DoubleArray(shape=list(data.shape), data=data.flatten()) @@ -44,6 +48,7 @@ def to_numpy(array_pb: DoubleArray) -> npt.NDArray[np.float64]: def to_numpy( array_pb: Union[IntArray, Int32Array, DoubleArray] ) -> Union[npt.NDArray[np.int64], npt.NDArray[np.int32], npt.NDArray[np.float64]]: + """Convert a protubuf array message to a numpy array.""" dtype = { IntArray: np.int64, Int32Array: np.int32, @@ -56,6 +61,7 @@ def dataarray_to_numpy( array_pb: DataArray, dtype: Union[type[np.int32], type[np.int64], type[np.float64]], ) -> Union[npt.NDArray[np.int64], npt.NDArray[np.int32], npt.NDArray[np.float64]]: + """Convert a DataArray protobuf message to a numpy array.""" data_array_attribute = array_pb.WhichOneof("data") if data_array_attribute is None: raise RuntimeError("None of the 'DataArray' data attributes are set!") diff --git a/src/ansys/acp/core/_utils/example_helpers.py b/src/ansys/acp/core/_utils/example_helpers.py index 1bf8cf6232..bc18617704 100644 --- a/src/ansys/acp/core/_utils/example_helpers.py +++ b/src/ansys/acp/core/_utils/example_helpers.py @@ -15,9 +15,7 @@ class _ExampleLocation: class ExampleKeys(Enum): - """ - Keys for the example files. - """ + """Keys for the example files.""" BASIC_FLAT_PLATE_CDB = auto() BASIC_FLAT_PLATE_ACPH5 = auto() @@ -34,7 +32,7 @@ class ExampleKeys(Enum): def get_example_file(example_key: ExampleKeys, working_directory: pathlib.Path) -> pathlib.Path: - """Downloads an example file from the example-data repo to the working directory. + """Download an example file from the example-data repo to the working directory. Parameters ---------- diff --git a/src/ansys/acp/core/_utils/path_to_str.py b/src/ansys/acp/core/_utils/path_to_str.py index 8c80423f87..0517e7550d 100644 --- a/src/ansys/acp/core/_utils/path_to_str.py +++ b/src/ansys/acp/core/_utils/path_to_str.py @@ -6,7 +6,7 @@ def path_to_str_checked(path: PATH) -> str: - """Converts a path to a string, with a type check.""" + """Convert a path to a string, with a type check.""" if isinstance(path, str): return path elif isinstance(path, PurePath): diff --git a/src/ansys/acp/core/_utils/property_protocols.py b/src/ansys/acp/core/_utils/property_protocols.py index 1d995d903a..c321d0673e 100644 --- a/src/ansys/acp/core/_utils/property_protocols.py +++ b/src/ansys/acp/core/_utils/property_protocols.py @@ -7,11 +7,23 @@ class ReadOnlyProperty(Generic[GetValueT_co], Protocol): + """Interface definition for read-only properties. + + The main purpose of this protocol is to improve the type hints for + properties which are created from helper functions. + """ + def __get__(self, obj: object, objtype: type | None = None) -> GetValueT_co: ... class ReadWriteProperty(Generic[GetValueT_co, SetValueT_contra], Protocol): + """Interface definition for read-write properties. + + The main purpose of this protocol is to improve the type hints for + properties which are created from helper functions. + """ + def __get__(self, obj: object, objtype: type | None = None) -> GetValueT_co: ... diff --git a/src/ansys/acp/core/_utils/resource_paths.py b/src/ansys/acp/core/_utils/resource_paths.py index 13fb0a22c3..bbe1c87795 100644 --- a/src/ansys/acp/core/_utils/resource_paths.py +++ b/src/ansys/acp/core/_utils/resource_paths.py @@ -4,7 +4,7 @@ def join(*parts: str) -> str: - """Joins parts of a Resource Path into a single string. + """Join parts of a Resource Path into a single string. Join parts of a Resource Path by slashes, ensuring that there are no double slashes in the result. Leading and trailing slashes are removed. @@ -13,12 +13,12 @@ def join(*parts: str) -> str: def to_parts(path: str) -> tuple[str, ...]: - """Returns a tuple representation of the given path.""" + """Get a tuple representation of the given path.""" return tuple(path.split("/")) def common_path(*paths: str) -> str: - """Returns the partial path that all input paths have in common.""" + """Get the partial path that all input paths have in common.""" common_parts = [] for path_parts in zip(*[to_parts(p) for p in paths]): first_path_part = path_parts[0] diff --git a/src/ansys/acp/core/_utils/visualization.py b/src/ansys/acp/core/_utils/visualization.py index a6bbd3f2fa..a1efb98a5b 100644 --- a/src/ansys/acp/core/_utils/visualization.py +++ b/src/ansys/acp/core/_utils/visualization.py @@ -8,6 +8,8 @@ class ElementType(IntEnum): + """Enumeration of ACP element types.""" + VERTEX_ELEMENT = 100 LINK2N3D = 101 BEAM2N3D = 111 @@ -94,7 +96,7 @@ def to_pyvista_faces( element_nodes: npt.NDArray[np.int32], element_nodes_offsets: npt.NDArray[np.int32], ) -> npt.NDArray[np.int32]: - """Converts ACP element data to PyVista faces.""" + """Convert ACP element data to PyVista faces.""" target_size = element_types.size + element_nodes.size # InterfaceElement12N and InterfaceElement16N are not supported by VTK; # they are shown as shell 3n and 4n, respectively. @@ -128,5 +130,5 @@ def to_pyvista_faces( def to_pyvista_types(element_types: npt.NDArray[np.int32]) -> npt.NDArray[np.int32]: - """Converts ACP element types to PyVista cell types.""" + """Convert ACP element types to PyVista cell types.""" return np.array([ELEMENT_TO_PYVISTA_TYPE[el_type] for el_type in element_types]) diff --git a/src/ansys/acp/core/_workflow.py b/src/ansys/acp/core/_workflow.py index 7cbfa69239..6792fe6e5f 100644 --- a/src/ansys/acp/core/_workflow.py +++ b/src/ansys/acp/core/_workflow.py @@ -180,7 +180,8 @@ def get_local_cdb_file(self) -> pathlib.Path: """Get the cdb file on the local machine. Write the analysis model including the layup definition in cdb format, - copy it to the local working directory and return its path.""" + copy it to the local working directory and return its path. + """ return self._file_transfer_strategy.get_file( self._model.save_analysis_model, self._model.name + ".cdb" ) @@ -188,14 +189,16 @@ def get_local_cdb_file(self) -> pathlib.Path: def get_local_materials_file(self) -> pathlib.Path: """Get the materials.xml file on the local machine. - Write the materials.xml file, copy it to the local working directory and return its path.""" + Write the materials.xml file, copy it to the local working directory and return its path. + """ return self._file_transfer_strategy.get_file(self._model.export_materials, "materials.xml") def get_local_composite_definitions_file(self) -> pathlib.Path: """Get the composite definitions file on the local machine. - Write the composite definitions file, copy it - to the local working directory and return its path.""" + Write the composite definitions file, copy it to the local working + directory and return its path. + """ return self._file_transfer_strategy.get_file( self._model.export_shell_composite_definitions, "ACPCompositeDefinitions.h5" ) @@ -203,8 +206,9 @@ def get_local_composite_definitions_file(self) -> pathlib.Path: def get_local_acp_h5_file(self) -> pathlib.Path: """Get the ACP Project file (in acph5 format) on the local machine. - Save the acp model to an acph5 file, copy it - to the local working directory and return its path.""" + Save the acp model to an acph5 file, copy it to the local working + directory and return its path. + """ return self._file_transfer_strategy.get_file(self._model.save, self._model.name + ".acph5") def _add_input_file(self, path: pathlib.Path) -> pathlib.PurePath: