From f6e3bb4ba61dfaef4f29eefa9ac7f29070d9685d Mon Sep 17 00:00:00 2001 From: RaphaelHeiniger Date: Tue, 4 Feb 2025 17:28:20 +0100 Subject: [PATCH 1/3] fix: keyword not properly read due to missing ID / HEADING card (Issue #696) --- codegen/additional-cards.json | 6 +++ codegen/manifest.json | 50 +++++++++++++++++++ .../auto/boundary_prescribed_motion_node.py | 49 ++++++++++++++++++ .../auto/boundary_prescribed_motion_rigid.py | 49 ++++++++++++++++++ ...y_prescribed_motion_rigid_bndout2dynain.py | 49 ++++++++++++++++++ .../boundary_prescribed_motion_rigid_local.py | 49 ++++++++++++++++++ ...cribed_motion_rigid_local_bndout2dynain.py | 49 ++++++++++++++++++ .../auto/boundary_prescribed_motion_set.py | 49 ++++++++++++++++++ .../boundary_prescribed_motion_set_segment.py | 49 ++++++++++++++++++ .../keyword_classes/auto/boundary_spc_node.py | 49 ++++++++++++++++++ .../auto/boundary_spc_node_birth_death.py | 49 ++++++++++++++++++ .../keyword_classes/auto/boundary_spc_set.py | 49 ++++++++++++++++++ .../auto/boundary_spc_set_birth_death.py | 49 ++++++++++++++++++ 13 files changed, 595 insertions(+) diff --git a/codegen/additional-cards.json b/codegen/additional-cards.json index 6bc65500f..1d0e06d16 100644 --- a/codegen/additional-cards.json +++ b/codegen/additional-cards.json @@ -14,6 +14,12 @@ {"name": "ID", "type": "integer", "default": null, "position": 0, "width": 10, "help": "ID keyword option"} ] }, + "ID_HEADING": { + "fields": [ + {"name": "ID", "type": "integer", "default": null, "position": 0, "width": 10, "help": "ID keyword option"}, + {"name": "HEADING", "type": "string", "default": null, "position": 10, "width": 70, "help": "Descriptor. We suggest using unique descriptions."} + ] + }, "BLANK": { "fields": [ {"name": "__blank1", "type": "integer", "default": null, "position": 0, "used": false, "width": 10, "help": ""}, diff --git a/codegen/manifest.json b/codegen/manifest.json index 987f5f880..adbdc9618 100644 --- a/codegen/manifest.json +++ b/codegen/manifest.json @@ -32,6 +32,56 @@ ] } }, + { + "type": "prefix", + "patterns": ["BOUNDARY_PRESCRIBED_MOTION_NODE", + "BOUNDARY_PRESCRIBED_MOTION_SET", + "BOUNDARY_PRESCRIBED_MOTION_SET_SEGMENT", + "BOUNDARY_PRESCRIBED_MOTION_RIGID", + "BOUNDARY_PRESCRIBED_MOTION_RIGID_LOCAL" + ], + "exclusions": ["BOUNDARY_PRESCRIBED_MOTION_SET_BOX", + "BOUNDARY_PRESCRIBED_MOTION_SET_EDGE_UVW", + "BOUNDARY_PRESCRIBED_MOTION_SET_FACE_XYZ", + "BOUNDARY_PRESCRIBED_MOTION_SET_LINE", + "BOUNDARY_PRESCRIBED_MOTION_SET_POINT_UVW", + "BOUNDARY_PRESCRIBED_MOTION_SET_LINE" + ], + "generation-options": { + "add-option": [ + { + "card-order": -2, + "title-order": 1, + "cards": [ + { + "source": "additional-cards", + "card-name": "ID_HEADING" + } + ], + "option-name": "ID" + } + ] + } + }, + { + "type": "prefix", + "patterns": ["BOUNDARY_SPC_NODE", "BOUNDARY_SPC_SET"], + "generation-options": { + "add-option": [ + { + "card-order": -2, + "title-order": 1, + "cards": [ + { + "source": "additional-cards", + "card-name": "ID_HEADING" + } + ], + "option-name": "ID" + } + ] + } + }, { "type": "prefix", "patterns": ["CONSTRAINED_NODAL_RIGID_BODY"], diff --git a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_node.py b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_node.py index d39015b02..e509d1a70 100644 --- a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_node.py +++ b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_node.py @@ -23,6 +23,7 @@ import typing from ansys.dyna.core.lib.card import Card, Field, Flag from ansys.dyna.core.lib.config import use_lspp_defaults +from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec from ansys.dyna.core.lib.keyword_base import KeywordBase class BoundaryPrescribedMotionNode(KeywordBase): @@ -30,9 +31,13 @@ class BoundaryPrescribedMotionNode(KeywordBase): keyword = "BOUNDARY" subkeyword = "PRESCRIBED_MOTION_NODE" + option_specs = [ + OptionSpec("ID", -2, 1), + ] def __init__(self, **kwargs): super().__init__(**kwargs) + kwargs["parent"] = self self._cards = [ Card( [ @@ -134,6 +139,30 @@ def __init__(self, **kwargs): ], lambda: abs(self.dof) in [9, 10, 11] or self.vad==4, ), + OptionCardSet( + option_spec = BoundaryPrescribedMotionNode.option_specs[0], + cards = [ + Card( + [ + Field( + "id", + int, + 0, + 10, + kwargs.get("id") + ), + Field( + "heading", + str, + 10, + 70, + kwargs.get("heading") + ), + ], + ), + ], + **kwargs + ), ] @property @@ -292,3 +321,23 @@ def node2(self) -> int: def node2(self, value: int) -> None: self._cards[1].set_value("node2", value) + @property + def id(self) -> typing.Optional[int]: + """Get or set the ID keyword option + """ # nopep8 + return self._cards[2].cards[0].get_value("id") + + @id.setter + def id(self, value: int) -> None: + self._cards[2].cards[0].set_value("id", value) + + @property + def heading(self) -> typing.Optional[str]: + """Get or set the Descriptor. We suggest using unique descriptions. + """ # nopep8 + return self._cards[2].cards[0].get_value("heading") + + @heading.setter + def heading(self, value: str) -> None: + self._cards[2].cards[0].set_value("heading", value) + diff --git a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid.py b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid.py index 37e4287bd..0fea348eb 100644 --- a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid.py +++ b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid.py @@ -23,6 +23,7 @@ import typing from ansys.dyna.core.lib.card import Card, Field, Flag from ansys.dyna.core.lib.config import use_lspp_defaults +from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec from ansys.dyna.core.lib.keyword_base import KeywordBase class BoundaryPrescribedMotionRigid(KeywordBase): @@ -30,9 +31,13 @@ class BoundaryPrescribedMotionRigid(KeywordBase): keyword = "BOUNDARY" subkeyword = "PRESCRIBED_MOTION_RIGID" + option_specs = [ + OptionSpec("ID", -2, 1), + ] def __init__(self, **kwargs): super().__init__(**kwargs) + kwargs["parent"] = self self._cards = [ Card( [ @@ -134,6 +139,30 @@ def __init__(self, **kwargs): ], lambda: abs(self.dof) in [9, 10, 11] or self.vad==4, ), + OptionCardSet( + option_spec = BoundaryPrescribedMotionRigid.option_specs[0], + cards = [ + Card( + [ + Field( + "id", + int, + 0, + 10, + kwargs.get("id") + ), + Field( + "heading", + str, + 10, + 70, + kwargs.get("heading") + ), + ], + ), + ], + **kwargs + ), ] @property @@ -292,3 +321,23 @@ def node2(self) -> int: def node2(self, value: int) -> None: self._cards[1].set_value("node2", value) + @property + def id(self) -> typing.Optional[int]: + """Get or set the ID keyword option + """ # nopep8 + return self._cards[2].cards[0].get_value("id") + + @id.setter + def id(self, value: int) -> None: + self._cards[2].cards[0].set_value("id", value) + + @property + def heading(self) -> typing.Optional[str]: + """Get or set the Descriptor. We suggest using unique descriptions. + """ # nopep8 + return self._cards[2].cards[0].get_value("heading") + + @heading.setter + def heading(self, value: str) -> None: + self._cards[2].cards[0].set_value("heading", value) + diff --git a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid_bndout2dynain.py b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid_bndout2dynain.py index 1b6818b6d..508f7d1ce 100644 --- a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid_bndout2dynain.py +++ b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid_bndout2dynain.py @@ -23,6 +23,7 @@ import typing from ansys.dyna.core.lib.card import Card, Field, Flag from ansys.dyna.core.lib.config import use_lspp_defaults +from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec from ansys.dyna.core.lib.keyword_base import KeywordBase class BoundaryPrescribedMotionRigidBndout2Dynain(KeywordBase): @@ -30,9 +31,13 @@ class BoundaryPrescribedMotionRigidBndout2Dynain(KeywordBase): keyword = "BOUNDARY" subkeyword = "PRESCRIBED_MOTION_RIGID_BNDOUT2DYNAIN" + option_specs = [ + OptionSpec("ID", -2, 1), + ] def __init__(self, **kwargs): super().__init__(**kwargs) + kwargs["parent"] = self self._cards = [ Card( [ @@ -145,6 +150,30 @@ def __init__(self, **kwargs): ), ], ), + OptionCardSet( + option_spec = BoundaryPrescribedMotionRigidBndout2Dynain.option_specs[0], + cards = [ + Card( + [ + Field( + "id", + int, + 0, + 10, + kwargs.get("id") + ), + Field( + "heading", + str, + 10, + 70, + kwargs.get("heading") + ), + ], + ), + ], + **kwargs + ), ] @property @@ -317,3 +346,23 @@ def prmr(self) -> typing.Optional[str]: def prmr(self, value: str) -> None: self._cards[2].set_value("prmr", value) + @property + def id(self) -> typing.Optional[int]: + """Get or set the ID keyword option + """ # nopep8 + return self._cards[3].cards[0].get_value("id") + + @id.setter + def id(self, value: int) -> None: + self._cards[3].cards[0].set_value("id", value) + + @property + def heading(self) -> typing.Optional[str]: + """Get or set the Descriptor. We suggest using unique descriptions. + """ # nopep8 + return self._cards[3].cards[0].get_value("heading") + + @heading.setter + def heading(self, value: str) -> None: + self._cards[3].cards[0].set_value("heading", value) + diff --git a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid_local.py b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid_local.py index 1a350d53e..3cb735478 100644 --- a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid_local.py +++ b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid_local.py @@ -23,6 +23,7 @@ import typing from ansys.dyna.core.lib.card import Card, Field, Flag from ansys.dyna.core.lib.config import use_lspp_defaults +from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec from ansys.dyna.core.lib.keyword_base import KeywordBase class BoundaryPrescribedMotionRigidLocal(KeywordBase): @@ -30,9 +31,13 @@ class BoundaryPrescribedMotionRigidLocal(KeywordBase): keyword = "BOUNDARY" subkeyword = "PRESCRIBED_MOTION_RIGID_LOCAL" + option_specs = [ + OptionSpec("ID", -2, 1), + ] def __init__(self, **kwargs): super().__init__(**kwargs) + kwargs["parent"] = self self._cards = [ Card( [ @@ -134,6 +139,30 @@ def __init__(self, **kwargs): ], lambda: abs(self.dof) in [9, 10, 11] or self.vad==4, ), + OptionCardSet( + option_spec = BoundaryPrescribedMotionRigidLocal.option_specs[0], + cards = [ + Card( + [ + Field( + "id", + int, + 0, + 10, + kwargs.get("id") + ), + Field( + "heading", + str, + 10, + 70, + kwargs.get("heading") + ), + ], + ), + ], + **kwargs + ), ] @property @@ -292,3 +321,23 @@ def node2(self) -> int: def node2(self, value: int) -> None: self._cards[1].set_value("node2", value) + @property + def id(self) -> typing.Optional[int]: + """Get or set the ID keyword option + """ # nopep8 + return self._cards[2].cards[0].get_value("id") + + @id.setter + def id(self, value: int) -> None: + self._cards[2].cards[0].set_value("id", value) + + @property + def heading(self) -> typing.Optional[str]: + """Get or set the Descriptor. We suggest using unique descriptions. + """ # nopep8 + return self._cards[2].cards[0].get_value("heading") + + @heading.setter + def heading(self, value: str) -> None: + self._cards[2].cards[0].set_value("heading", value) + diff --git a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid_local_bndout2dynain.py b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid_local_bndout2dynain.py index 0042ac281..1f129715c 100644 --- a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid_local_bndout2dynain.py +++ b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_rigid_local_bndout2dynain.py @@ -23,6 +23,7 @@ import typing from ansys.dyna.core.lib.card import Card, Field, Flag from ansys.dyna.core.lib.config import use_lspp_defaults +from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec from ansys.dyna.core.lib.keyword_base import KeywordBase class BoundaryPrescribedMotionRigidLocalBndout2Dynain(KeywordBase): @@ -30,9 +31,13 @@ class BoundaryPrescribedMotionRigidLocalBndout2Dynain(KeywordBase): keyword = "BOUNDARY" subkeyword = "PRESCRIBED_MOTION_RIGID_LOCAL_BNDOUT2DYNAIN" + option_specs = [ + OptionSpec("ID", -2, 1), + ] def __init__(self, **kwargs): super().__init__(**kwargs) + kwargs["parent"] = self self._cards = [ Card( [ @@ -145,6 +150,30 @@ def __init__(self, **kwargs): ), ], ), + OptionCardSet( + option_spec = BoundaryPrescribedMotionRigidLocalBndout2Dynain.option_specs[0], + cards = [ + Card( + [ + Field( + "id", + int, + 0, + 10, + kwargs.get("id") + ), + Field( + "heading", + str, + 10, + 70, + kwargs.get("heading") + ), + ], + ), + ], + **kwargs + ), ] @property @@ -317,3 +346,23 @@ def prmr(self) -> typing.Optional[str]: def prmr(self, value: str) -> None: self._cards[2].set_value("prmr", value) + @property + def id(self) -> typing.Optional[int]: + """Get or set the ID keyword option + """ # nopep8 + return self._cards[3].cards[0].get_value("id") + + @id.setter + def id(self, value: int) -> None: + self._cards[3].cards[0].set_value("id", value) + + @property + def heading(self) -> typing.Optional[str]: + """Get or set the Descriptor. We suggest using unique descriptions. + """ # nopep8 + return self._cards[3].cards[0].get_value("heading") + + @heading.setter + def heading(self, value: str) -> None: + self._cards[3].cards[0].set_value("heading", value) + diff --git a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_set.py b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_set.py index 110841957..d08f10b12 100644 --- a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_set.py +++ b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_set.py @@ -23,6 +23,7 @@ import typing from ansys.dyna.core.lib.card import Card, Field, Flag from ansys.dyna.core.lib.config import use_lspp_defaults +from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec from ansys.dyna.core.lib.keyword_base import KeywordBase class BoundaryPrescribedMotionSet(KeywordBase): @@ -30,9 +31,13 @@ class BoundaryPrescribedMotionSet(KeywordBase): keyword = "BOUNDARY" subkeyword = "PRESCRIBED_MOTION_SET" + option_specs = [ + OptionSpec("ID", -2, 1), + ] def __init__(self, **kwargs): super().__init__(**kwargs) + kwargs["parent"] = self self._cards = [ Card( [ @@ -134,6 +139,30 @@ def __init__(self, **kwargs): ], lambda: abs(self.dof) in [9, 10, 11] or self.vad==4, ), + OptionCardSet( + option_spec = BoundaryPrescribedMotionSet.option_specs[0], + cards = [ + Card( + [ + Field( + "id", + int, + 0, + 10, + kwargs.get("id") + ), + Field( + "heading", + str, + 10, + 70, + kwargs.get("heading") + ), + ], + ), + ], + **kwargs + ), ] @property @@ -293,3 +322,23 @@ def node2(self) -> int: def node2(self, value: int) -> None: self._cards[1].set_value("node2", value) + @property + def id(self) -> typing.Optional[int]: + """Get or set the ID keyword option + """ # nopep8 + return self._cards[2].cards[0].get_value("id") + + @id.setter + def id(self, value: int) -> None: + self._cards[2].cards[0].set_value("id", value) + + @property + def heading(self) -> typing.Optional[str]: + """Get or set the Descriptor. We suggest using unique descriptions. + """ # nopep8 + return self._cards[2].cards[0].get_value("heading") + + @heading.setter + def heading(self, value: str) -> None: + self._cards[2].cards[0].set_value("heading", value) + diff --git a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_set_segment.py b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_set_segment.py index e07e7763b..d684a8171 100644 --- a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_set_segment.py +++ b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_prescribed_motion_set_segment.py @@ -23,6 +23,7 @@ import typing from ansys.dyna.core.lib.card import Card, Field, Flag from ansys.dyna.core.lib.config import use_lspp_defaults +from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec from ansys.dyna.core.lib.keyword_base import KeywordBase class BoundaryPrescribedMotionSetSegment(KeywordBase): @@ -30,9 +31,13 @@ class BoundaryPrescribedMotionSetSegment(KeywordBase): keyword = "BOUNDARY" subkeyword = "PRESCRIBED_MOTION_SET_SEGMENT" + option_specs = [ + OptionSpec("ID", -2, 1), + ] def __init__(self, **kwargs): super().__init__(**kwargs) + kwargs["parent"] = self self._cards = [ Card( [ @@ -94,6 +99,30 @@ def __init__(self, **kwargs): ), ], ), + OptionCardSet( + option_spec = BoundaryPrescribedMotionSetSegment.option_specs[0], + cards = [ + Card( + [ + Field( + "id", + int, + 0, + 10, + kwargs.get("id") + ), + Field( + "heading", + str, + 10, + 70, + kwargs.get("heading") + ), + ], + ), + ], + **kwargs + ), ] @property @@ -203,3 +232,23 @@ def birth(self) -> float: def birth(self, value: float) -> None: self._cards[0].set_value("birth", value) + @property + def id(self) -> typing.Optional[int]: + """Get or set the ID keyword option + """ # nopep8 + return self._cards[1].cards[0].get_value("id") + + @id.setter + def id(self, value: int) -> None: + self._cards[1].cards[0].set_value("id", value) + + @property + def heading(self) -> typing.Optional[str]: + """Get or set the Descriptor. We suggest using unique descriptions. + """ # nopep8 + return self._cards[1].cards[0].get_value("heading") + + @heading.setter + def heading(self, value: str) -> None: + self._cards[1].cards[0].set_value("heading", value) + diff --git a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_node.py b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_node.py index 5eebca330..0ddb35a9b 100644 --- a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_node.py +++ b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_node.py @@ -24,6 +24,7 @@ from ansys.dyna.core.lib.card import Card, Field, Flag from ansys.dyna.core.lib.config import use_lspp_defaults from ansys.dyna.core.lib.duplicate_card import DuplicateCard +from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec from ansys.dyna.core.lib.keyword_base import KeywordBase class BoundarySpcNode(KeywordBase): @@ -31,9 +32,13 @@ class BoundarySpcNode(KeywordBase): keyword = "BOUNDARY" subkeyword = "SPC_NODE" + option_specs = [ + OptionSpec("ID", -2, 1), + ] def __init__(self, **kwargs): super().__init__(**kwargs) + kwargs["parent"] = self self._cards = [ DuplicateCard( [ @@ -48,6 +53,30 @@ def __init__(self, **kwargs): ], None, data = kwargs.get("nodes")), + OptionCardSet( + option_spec = BoundarySpcNode.option_specs[0], + cards = [ + Card( + [ + Field( + "id", + int, + 0, + 10, + kwargs.get("id") + ), + Field( + "heading", + str, + 10, + 70, + kwargs.get("heading") + ), + ], + ), + ], + **kwargs + ), ] @property @@ -60,3 +89,23 @@ def nodes(self, df): '''sets nodes from the dataframe df''' self._cards[0].table = df + @property + def id(self) -> typing.Optional[int]: + """Get or set the ID keyword option + """ # nopep8 + return self._cards[1].cards[0].get_value("id") + + @id.setter + def id(self, value: int) -> None: + self._cards[1].cards[0].set_value("id", value) + + @property + def heading(self) -> typing.Optional[str]: + """Get or set the Descriptor. We suggest using unique descriptions. + """ # nopep8 + return self._cards[1].cards[0].get_value("heading") + + @heading.setter + def heading(self, value: str) -> None: + self._cards[1].cards[0].set_value("heading", value) + diff --git a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_node_birth_death.py b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_node_birth_death.py index 121a3fbd3..17e0a691c 100644 --- a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_node_birth_death.py +++ b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_node_birth_death.py @@ -23,6 +23,7 @@ import typing from ansys.dyna.core.lib.card import Card, Field, Flag from ansys.dyna.core.lib.config import use_lspp_defaults +from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec from ansys.dyna.core.lib.keyword_base import KeywordBase class BoundarySpcNodeBirthDeath(KeywordBase): @@ -30,9 +31,13 @@ class BoundarySpcNodeBirthDeath(KeywordBase): keyword = "BOUNDARY" subkeyword = "SPC_NODE_BIRTH_DEATH" + option_specs = [ + OptionSpec("ID", -2, 1), + ] def __init__(self, **kwargs): super().__init__(**kwargs) + kwargs["parent"] = self self._cards = [ Card( [ @@ -112,6 +117,30 @@ def __init__(self, **kwargs): ), ], ), + OptionCardSet( + option_spec = BoundarySpcNodeBirthDeath.option_specs[0], + cards = [ + Card( + [ + Field( + "id", + int, + 0, + 10, + kwargs.get("id") + ), + Field( + "heading", + str, + 10, + 70, + kwargs.get("heading") + ), + ], + ), + ], + **kwargs + ), ] @property @@ -232,3 +261,23 @@ def death(self) -> float: def death(self, value: float) -> None: self._cards[1].set_value("death", value) + @property + def id(self) -> typing.Optional[int]: + """Get or set the ID keyword option + """ # nopep8 + return self._cards[2].cards[0].get_value("id") + + @id.setter + def id(self, value: int) -> None: + self._cards[2].cards[0].set_value("id", value) + + @property + def heading(self) -> typing.Optional[str]: + """Get or set the Descriptor. We suggest using unique descriptions. + """ # nopep8 + return self._cards[2].cards[0].get_value("heading") + + @heading.setter + def heading(self, value: str) -> None: + self._cards[2].cards[0].set_value("heading", value) + diff --git a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_set.py b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_set.py index 2fbc67360..e65f9431b 100644 --- a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_set.py +++ b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_set.py @@ -23,6 +23,7 @@ import typing from ansys.dyna.core.lib.card import Card, Field, Flag from ansys.dyna.core.lib.config import use_lspp_defaults +from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec from ansys.dyna.core.lib.keyword_base import KeywordBase class BoundarySpcSet(KeywordBase): @@ -30,9 +31,13 @@ class BoundarySpcSet(KeywordBase): keyword = "BOUNDARY" subkeyword = "SPC_SET" + option_specs = [ + OptionSpec("ID", -2, 1), + ] def __init__(self, **kwargs): super().__init__(**kwargs) + kwargs["parent"] = self self._cards = [ Card( [ @@ -94,6 +99,30 @@ def __init__(self, **kwargs): ), ], ), + OptionCardSet( + option_spec = BoundarySpcSet.option_specs[0], + cards = [ + Card( + [ + Field( + "id", + int, + 0, + 10, + kwargs.get("id") + ), + Field( + "heading", + str, + 10, + 70, + kwargs.get("heading") + ), + ], + ), + ], + **kwargs + ), ] @property @@ -194,3 +223,23 @@ def dofrz(self, value: int) -> None: raise Exception("""dofrz must be one of {0,1}""") self._cards[0].set_value("dofrz", value) + @property + def id(self) -> typing.Optional[int]: + """Get or set the ID keyword option + """ # nopep8 + return self._cards[1].cards[0].get_value("id") + + @id.setter + def id(self, value: int) -> None: + self._cards[1].cards[0].set_value("id", value) + + @property + def heading(self) -> typing.Optional[str]: + """Get or set the Descriptor. We suggest using unique descriptions. + """ # nopep8 + return self._cards[1].cards[0].get_value("heading") + + @heading.setter + def heading(self, value: str) -> None: + self._cards[1].cards[0].set_value("heading", value) + diff --git a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_set_birth_death.py b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_set_birth_death.py index 811c56e38..011c68ffc 100644 --- a/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_set_birth_death.py +++ b/src/ansys/dyna/core/keywords/keyword_classes/auto/boundary_spc_set_birth_death.py @@ -23,6 +23,7 @@ import typing from ansys.dyna.core.lib.card import Card, Field, Flag from ansys.dyna.core.lib.config import use_lspp_defaults +from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec from ansys.dyna.core.lib.keyword_base import KeywordBase class BoundarySpcSetBirthDeath(KeywordBase): @@ -30,9 +31,13 @@ class BoundarySpcSetBirthDeath(KeywordBase): keyword = "BOUNDARY" subkeyword = "SPC_SET_BIRTH_DEATH" + option_specs = [ + OptionSpec("ID", -2, 1), + ] def __init__(self, **kwargs): super().__init__(**kwargs) + kwargs["parent"] = self self._cards = [ Card( [ @@ -112,6 +117,30 @@ def __init__(self, **kwargs): ), ], ), + OptionCardSet( + option_spec = BoundarySpcSetBirthDeath.option_specs[0], + cards = [ + Card( + [ + Field( + "id", + int, + 0, + 10, + kwargs.get("id") + ), + Field( + "heading", + str, + 10, + 70, + kwargs.get("heading") + ), + ], + ), + ], + **kwargs + ), ] @property @@ -232,3 +261,23 @@ def death(self) -> float: def death(self, value: float) -> None: self._cards[1].set_value("death", value) + @property + def id(self) -> typing.Optional[int]: + """Get or set the ID keyword option + """ # nopep8 + return self._cards[2].cards[0].get_value("id") + + @id.setter + def id(self, value: int) -> None: + self._cards[2].cards[0].set_value("id", value) + + @property + def heading(self) -> typing.Optional[str]: + """Get or set the Descriptor. We suggest using unique descriptions. + """ # nopep8 + return self._cards[2].cards[0].get_value("heading") + + @heading.setter + def heading(self, value: str) -> None: + self._cards[2].cards[0].set_value("heading", value) + From 5e6d3a66816501992bf15d41b77af5e436e8372f Mon Sep 17 00:00:00 2001 From: RaphaelHeiniger Date: Fri, 7 Feb 2025 17:56:52 +0100 Subject: [PATCH 2/3] fix: correctly read the CONTROL_MPP_DECOMPOSITION_TRANSFORMATION card. Handles optional card 2 which is activated by certain types. Ultimately a single dataframe is created. The keyword is written correctly as well. However due to the single dataframe comment lines inbetween get lost. (Issue #696) --- codegen/manifest.json | 16 ++ ...ontrol_mpp_decomposition_transformation.py | 253 ++++++------------ tests/test_keywords.py | 8 + tests/testfiles/keywords/reference_string.py | 41 +++ 4 files changed, 144 insertions(+), 174 deletions(-) diff --git a/codegen/manifest.json b/codegen/manifest.json index adbdc9618..c0c96521c 100644 --- a/codegen/manifest.json +++ b/codegen/manifest.json @@ -517,6 +517,22 @@ }, "comment": "a mix of conditional, variable length, and duplicate cards" }, + "CONTROL_MPP_DECOMPOSITION_TRANSFORMATION" : { + "generation-options": { + "conditional-card": [ + { + "index": 1, + "func": "not self.transformation.empty and self.transformation['type'].iloc[-1] in ['VEC3', 'C2R', 'S2R', 'MAT']" + } + ], + "duplicate-card-group": [ + { + "indices": [0, 1], + "overall-name": "transformation" + } + ] + } + }, "CONTROL_REFERENCE_CONFIGURAION": { "type": "multiple", "generations": [ diff --git a/src/ansys/dyna/core/keywords/keyword_classes/auto/control_mpp_decomposition_transformation.py b/src/ansys/dyna/core/keywords/keyword_classes/auto/control_mpp_decomposition_transformation.py index 4256bbff7..8a13ce63e 100644 --- a/src/ansys/dyna/core/keywords/keyword_classes/auto/control_mpp_decomposition_transformation.py +++ b/src/ansys/dyna/core/keywords/keyword_classes/auto/control_mpp_decomposition_transformation.py @@ -23,6 +23,7 @@ import typing from ansys.dyna.core.lib.card import Card, Field, Flag from ansys.dyna.core.lib.config import use_lspp_defaults +from ansys.dyna.core.lib.duplicate_card_group import DuplicateCardGroup from ansys.dyna.core.lib.keyword_base import KeywordBase class ControlMppDecompositionTransformation(KeywordBase): @@ -34,185 +35,89 @@ class ControlMppDecompositionTransformation(KeywordBase): def __init__(self, **kwargs): super().__init__(**kwargs) self._cards = [ - Card( + DuplicateCardGroup( [ - Field( - "type", - str, - 0, - 10, - kwargs.get("type", "RX" if use_lspp_defaults() else None) + Card( + [ + Field( + "type", + str, + 0, + 10, + ), + Field( + "v1", + float, + 10, + 10, + ), + Field( + "v2", + float, + 20, + 10, + ), + Field( + "v3", + float, + 30, + 10, + ), + Field( + "v4", + float, + 40, + 10, + ), + Field( + "v5", + float, + 50, + 10, + ), + Field( + "v6", + float, + 60, + 10, + ), + ], ), - Field( - "v1", - float, - 10, - 10, - kwargs.get("v1", 0.0 if use_lspp_defaults() else None) - ), - Field( - "v2", - float, - 20, - 10, - kwargs.get("v2", 0.0 if use_lspp_defaults() else None) - ), - Field( - "v3", - float, - 30, - 10, - kwargs.get("v3", 0.0 if use_lspp_defaults() else None) - ), - Field( - "v4", - float, - 40, - 10, - kwargs.get("v4", 0.0 if use_lspp_defaults() else None) - ), - Field( - "v5", - float, - 50, - 10, - kwargs.get("v5", 0.0 if use_lspp_defaults() else None) - ), - Field( - "v6", - float, - 60, - 10, - kwargs.get("v6", 0.0 if use_lspp_defaults() else None) - ), - ], - ), - Card( - [ - Field( - "v7", - float, - 0, - 10, - kwargs.get("v7", 0.0 if use_lspp_defaults() else None) - ), - Field( - "v8", - float, - 10, - 10, - kwargs.get("v8", 0.0 if use_lspp_defaults() else None) - ), - Field( - "v9", - float, - 20, - 10, - kwargs.get("v9", 0.0 if use_lspp_defaults() else None) + Card( + [ + Field( + "v7", + float, + 0, + 10, + ), + Field( + "v8", + float, + 10, + 10, + ), + Field( + "v9", + float, + 20, + 10, + ), + ], + lambda: not self.transformation.empty and self.transformation['type'].iloc[-1] in ['VEC3', 'C2R', 'S2R', 'MAT'], ), ], - ), + None, + data = kwargs.get("transformation")), ] @property - def type(self) -> str: - """Get or set the Which transformation to apply. The possible values are :VEC3,C2R,S2R,MAT. - """ # nopep8 - return self._cards[0].get_value("type") - - @type.setter - def type(self, value: str) -> None: - if value not in ["RX", "RY", "RZ", "SX", "SY", "SZ", "VEC3", "C2R", "S2R", "MAT"]: - raise Exception("""type must be one of {"RX","RY","RZ","SX","SY","SZ","VEC3","C2R","S2R","MAT"}""") - self._cards[0].set_value("type", value) - - @property - def v1(self) -> float: - """Get or set the Parameters to the transformation. - """ # nopep8 - return self._cards[0].get_value("v1") - - @v1.setter - def v1(self, value: float) -> None: - self._cards[0].set_value("v1", value) - - @property - def v2(self) -> float: - """Get or set the Parameters to the transformation. - """ # nopep8 - return self._cards[0].get_value("v2") - - @v2.setter - def v2(self, value: float) -> None: - self._cards[0].set_value("v2", value) - - @property - def v3(self) -> float: - """Get or set the Parameters to the transformation. - """ # nopep8 - return self._cards[0].get_value("v3") - - @v3.setter - def v3(self, value: float) -> None: - self._cards[0].set_value("v3", value) - - @property - def v4(self) -> float: - """Get or set the Parameters to the transformation. - """ # nopep8 - return self._cards[0].get_value("v4") - - @v4.setter - def v4(self, value: float) -> None: - self._cards[0].set_value("v4", value) - - @property - def v5(self) -> float: - """Get or set the Parameters to the transformation. - """ # nopep8 - return self._cards[0].get_value("v5") - - @v5.setter - def v5(self, value: float) -> None: - self._cards[0].set_value("v5", value) - - @property - def v6(self) -> float: - """Get or set the Parameters to the transformation. - """ # nopep8 - return self._cards[0].get_value("v6") - - @v6.setter - def v6(self, value: float) -> None: - self._cards[0].set_value("v6", value) - - @property - def v7(self) -> float: - """Get or set the Parameters to the transformation. - """ # nopep8 - return self._cards[1].get_value("v7") - - @v7.setter - def v7(self, value: float) -> None: - self._cards[1].set_value("v7", value) - - @property - def v8(self) -> float: - """Get or set the Parameters to the transformation. - """ # nopep8 - return self._cards[1].get_value("v8") - - @v8.setter - def v8(self, value: float) -> None: - self._cards[1].set_value("v8", value) - - @property - def v9(self) -> float: - """Get or set the Parameters to the transformation. - """ # nopep8 - return self._cards[1].get_value("v9") - - @v9.setter - def v9(self, value: float) -> None: - self._cards[1].set_value("v9", value) + def transformation(self): + '''Gets the full table of transformation''' + return self._cards[0].table + + @transformation.setter + def transformation(self, df): + '''sets transformation from the dataframe df''' + self._cards[0].table = df diff --git a/tests/test_keywords.py b/tests/test_keywords.py index 70550d34c..6f6abc830 100644 --- a/tests/test_keywords.py +++ b/tests/test_keywords.py @@ -436,6 +436,14 @@ def test_element_solid_ortho(ref_string): assert len(elements.cards[0]._cards) == 3 +@pytest.mark.keywords +def test_control_mpp_decomposition_transformation(ref_string): + """Read CONTROL_MPP_DECOMPOSITION_TRANSFORMATION""" + c = kwd.ControlMppDecompositionTransformation() + c.loads(ref_string.test_control_mpp_decomposition_transformation_string_read) + assert ref_string.test_control_mpp_decomposition_transformation_string_write == c.write() + + @pytest.mark.keywords def test_control_time_step_read(ref_string): """Read CONTROL_TIME_STEP""" diff --git a/tests/testfiles/keywords/reference_string.py b/tests/testfiles/keywords/reference_string.py index ce3d62235..5bc9092b0 100644 --- a/tests/testfiles/keywords/reference_string.py +++ b/tests/testfiles/keywords/reference_string.py @@ -360,6 +360,47 @@ 59 0.1 0.2 0.3 ...console output truncated at 60 rows""" + +test_control_mpp_decomposition_transformation_string_read = """*CONTROL_MPP_DECOMPOSITION_TRANSFORMATION +$# type v1 v2 v3 v4 v5 v6 +VEC3 0.0 0.0 0.0 0.0 0.0 0.0 +$# v7 v8 v9 + 0.0 0.0 0.0 +$# type v1 v2 v3 v4 v5 v6 +SY 0.0 0.0 0.0 0.0 0.0 0.0 +$# type v1 v2 v3 v4 v5 v6 +MAT 0.0 0.0 0.0 0.0 0.0 0.0 +$# v7 v8 v9 + 0.0 0.0 0.0 +$# type v1 v2 v3 v4 v5 v6 +RX 0.0 0.0 0.0 0.0 0.0 0.0 +$# type v1 v2 v3 v4 v5 v6 +S2R 0.0 0.0 0.0 0.0 0.0 0.0 +$# v7 v8 v9 + 0.0 0.0 0.0 +$# type v1 v2 v3 v4 v5 v6 +RZ 0.0 0.0 0.0 0.0 0.0 0.0 +$# type v1 v2 v3 v4 v5 v6 +VEC3 0.0 0.0 0.0 0.0 0.0 0.0 +$# v7 v8 v9 + 0.0 0.0 0.0""" + + +test_control_mpp_decomposition_transformation_string_write = """*CONTROL_MPP_DECOMPOSITION_TRANSFORMATION +$# type v1 v2 v3 v4 v5 v6 +VEC3 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 0.0 0.0 +SY 0.0 0.0 0.0 0.0 0.0 0.0 +MAT 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 0.0 0.0 +RX 0.0 0.0 0.0 0.0 0.0 0.0 +S2R 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 0.0 0.0 +RZ 0.0 0.0 0.0 0.0 0.0 0.0 +VEC3 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 0.0 0.0 """ + + test_control_time_step_string = """*CONTROL_TIME_STEP $# dtinit tssfac isdo tslimt dt2ms lctm erode ms1st 0.000 1.000000 0 0.000 1 0 0 0 From a9fda6ed0ba837e2793d9b50cd14c38d86b9da94 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Fri, 7 Feb 2025 17:15:26 +0000 Subject: [PATCH 3/3] chore: adding changelog file 701.added.md [dependabot-skip] --- doc/changelog/701.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog/701.added.md diff --git a/doc/changelog/701.added.md b/doc/changelog/701.added.md new file mode 100644 index 000000000..df9775ecd --- /dev/null +++ b/doc/changelog/701.added.md @@ -0,0 +1 @@ +fix: BOUNDARY_PRESCRIBED_MOTION_*_ID option and CONTROL_MPP_DECOMPOSITION_TRANSFORMATION (Issue #696) \ No newline at end of file