Skip to content

Commit 39974e3

Browse files
koubaaMohamed Koubaapyansys-ci-botpre-commit-ci[bot]
authored
fix: Fix some contact keyword issues (#742)
Co-authored-by: Mohamed Koubaa <[email protected]> Co-authored-by: pyansys-ci-bot <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 8c4be07 commit 39974e3

File tree

13 files changed

+326
-13
lines changed

13 files changed

+326
-13
lines changed

codegen/manifest.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,25 @@
123123
]
124124
}
125125
},
126+
{
127+
"type": "prefix",
128+
"patterns": ["CONTACT_FORCE_TRANSDUCER"],
129+
"generation-options": {
130+
"add-option": [
131+
{
132+
"card-order": -2,
133+
"title-order": 1,
134+
"cards": [
135+
{
136+
"source": "additional-cards",
137+
"card-name": "CONTACT_ID"
138+
}
139+
],
140+
"option-name": "ID"
141+
}
142+
]
143+
}
144+
},
126145
{
127146
"type": "prefix",
128147
"patterns": ["CONTACT"],

doc/changelog/742.miscellaneous.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix issues

src/ansys/dyna/core/keywords/keyword_classes/auto/contact_force_transducer.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,21 @@
2222

2323
import typing
2424
from ansys.dyna.core.lib.card import Card, Field, Flag
25+
from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec
2526
from ansys.dyna.core.lib.keyword_base import KeywordBase
2627

2728
class ContactForceTransducer(KeywordBase):
2829
"""DYNA CONTACT_FORCE_TRANSDUCER keyword"""
2930

3031
keyword = "CONTACT"
3132
subkeyword = "FORCE_TRANSDUCER"
33+
option_specs = [
34+
OptionSpec("ID", -2, 1),
35+
]
3236

3337
def __init__(self, **kwargs):
3438
super().__init__(**kwargs)
39+
kwargs["parent"] = self
3540
self._cards = [
3641
Card(
3742
[
@@ -217,6 +222,30 @@ def __init__(self, **kwargs):
217222
),
218223
],
219224
),
225+
OptionCardSet(
226+
option_spec = ContactForceTransducer.option_specs[0],
227+
cards = [
228+
Card(
229+
[
230+
Field(
231+
"cid",
232+
int,
233+
0,
234+
10,
235+
kwargs.get("cid")
236+
),
237+
Field(
238+
"heading",
239+
str,
240+
10,
241+
70,
242+
kwargs.get("heading")
243+
),
244+
],
245+
),
246+
],
247+
**kwargs
248+
),
220249
]
221250

222251
@property
@@ -330,3 +359,23 @@ def sbpr(self, value: int) -> None:
330359
raise Exception("""sbpr must be `None` or one of {0,1,2}""")
331360
self._cards[0].set_value("sbpr", value)
332361

362+
@property
363+
def cid(self) -> typing.Optional[int]:
364+
"""Get or set the ID keyword option
365+
""" # nopep8
366+
return self._cards[3].cards[0].get_value("cid")
367+
368+
@cid.setter
369+
def cid(self, value: int) -> None:
370+
self._cards[3].cards[0].set_value("cid", value)
371+
372+
@property
373+
def heading(self) -> typing.Optional[str]:
374+
"""Get or set the Interface descriptor. We suggest using unique descriptions.
375+
""" # nopep8
376+
return self._cards[3].cards[0].get_value("heading")
377+
378+
@heading.setter
379+
def heading(self, value: str) -> None:
380+
self._cards[3].cards[0].set_value("heading", value)
381+

src/ansys/dyna/core/keywords/keyword_classes/auto/contact_force_transducer_constraint.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,21 @@
2222

2323
import typing
2424
from ansys.dyna.core.lib.card import Card, Field, Flag
25+
from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec
2526
from ansys.dyna.core.lib.keyword_base import KeywordBase
2627

2728
class ContactForceTransducerConstraint(KeywordBase):
2829
"""DYNA CONTACT_FORCE_TRANSDUCER_CONSTRAINT keyword"""
2930

3031
keyword = "CONTACT"
3132
subkeyword = "FORCE_TRANSDUCER_CONSTRAINT"
33+
option_specs = [
34+
OptionSpec("ID", -2, 1),
35+
]
3236

3337
def __init__(self, **kwargs):
3438
super().__init__(**kwargs)
39+
kwargs["parent"] = self
3540
self._cards = [
3641
Card(
3742
[
@@ -217,6 +222,30 @@ def __init__(self, **kwargs):
217222
),
218223
],
219224
),
225+
OptionCardSet(
226+
option_spec = ContactForceTransducerConstraint.option_specs[0],
227+
cards = [
228+
Card(
229+
[
230+
Field(
231+
"cid",
232+
int,
233+
0,
234+
10,
235+
kwargs.get("cid")
236+
),
237+
Field(
238+
"heading",
239+
str,
240+
10,
241+
70,
242+
kwargs.get("heading")
243+
),
244+
],
245+
),
246+
],
247+
**kwargs
248+
),
220249
]
221250

222251
@property
@@ -330,3 +359,23 @@ def sbpr(self, value: int) -> None:
330359
raise Exception("""sbpr must be `None` or one of {0,1,2}""")
331360
self._cards[0].set_value("sbpr", value)
332361

362+
@property
363+
def cid(self) -> typing.Optional[int]:
364+
"""Get or set the ID keyword option
365+
""" # nopep8
366+
return self._cards[3].cards[0].get_value("cid")
367+
368+
@cid.setter
369+
def cid(self, value: int) -> None:
370+
self._cards[3].cards[0].set_value("cid", value)
371+
372+
@property
373+
def heading(self) -> typing.Optional[str]:
374+
"""Get or set the Interface descriptor. We suggest using unique descriptions.
375+
""" # nopep8
376+
return self._cards[3].cards[0].get_value("heading")
377+
378+
@heading.setter
379+
def heading(self, value: str) -> None:
380+
self._cards[3].cards[0].set_value("heading", value)
381+

src/ansys/dyna/core/keywords/keyword_classes/auto/contact_force_transducer_penalty.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,21 @@
2222

2323
import typing
2424
from ansys.dyna.core.lib.card import Card, Field, Flag
25+
from ansys.dyna.core.lib.option_card import OptionCardSet, OptionSpec
2526
from ansys.dyna.core.lib.keyword_base import KeywordBase
2627

2728
class ContactForceTransducerPenalty(KeywordBase):
2829
"""DYNA CONTACT_FORCE_TRANSDUCER_PENALTY keyword"""
2930

3031
keyword = "CONTACT"
3132
subkeyword = "FORCE_TRANSDUCER_PENALTY"
33+
option_specs = [
34+
OptionSpec("ID", -2, 1),
35+
]
3236

3337
def __init__(self, **kwargs):
3438
super().__init__(**kwargs)
39+
kwargs["parent"] = self
3540
self._cards = [
3641
Card(
3742
[
@@ -217,6 +222,30 @@ def __init__(self, **kwargs):
217222
),
218223
],
219224
),
225+
OptionCardSet(
226+
option_spec = ContactForceTransducerPenalty.option_specs[0],
227+
cards = [
228+
Card(
229+
[
230+
Field(
231+
"cid",
232+
int,
233+
0,
234+
10,
235+
kwargs.get("cid")
236+
),
237+
Field(
238+
"heading",
239+
str,
240+
10,
241+
70,
242+
kwargs.get("heading")
243+
),
244+
],
245+
),
246+
],
247+
**kwargs
248+
),
220249
]
221250

222251
@property
@@ -330,3 +359,23 @@ def sbpr(self, value: int) -> None:
330359
raise Exception("""sbpr must be `None` or one of {0,1,2}""")
331360
self._cards[0].set_value("sbpr", value)
332361

362+
@property
363+
def cid(self) -> typing.Optional[int]:
364+
"""Get or set the ID keyword option
365+
""" # nopep8
366+
return self._cards[3].cards[0].get_value("cid")
367+
368+
@cid.setter
369+
def cid(self, value: int) -> None:
370+
self._cards[3].cards[0].set_value("cid", value)
371+
372+
@property
373+
def heading(self) -> typing.Optional[str]:
374+
"""Get or set the Interface descriptor. We suggest using unique descriptions.
375+
""" # nopep8
376+
return self._cards[3].cards[0].get_value("heading")
377+
378+
@heading.setter
379+
def heading(self, value: str) -> None:
380+
self._cards[3].cards[0].set_value("heading", value)
381+

src/ansys/dyna/core/lib/field.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def width(self, value: int) -> None:
8989

9090
@property
9191
def value(self) -> typing.Any:
92-
if self._truthy_value(self._value) and type(self._value) == Flag:
92+
if type(self._value) == Flag:
9393
return self._value.value
9494
return self._value
9595

@@ -103,18 +103,18 @@ def _no_value_flag(self, value) -> bool:
103103

104104
@value.setter
105105
def value(self, value: typing.Any) -> None:
106-
no_value_flag = self._no_value_flag(value)
107-
if no_value_flag:
106+
if type(self._value) == Flag:
108107
self._value.value = value
109108
else:
110109
self._value = value
111110

112111
def io_info(self) -> typing.Tuple[str, typing.Type]:
113112
"""Return the value and type used for io."""
114-
no_value_flag = self._no_value_flag(self._value)
115-
if no_value_flag:
116-
value = self._value.true_value if self._value.value else self._value.false_value
117-
return value, str
113+
if type(self._value) == Flag:
114+
if self._value.value:
115+
return self._value.true_value, str
116+
else:
117+
return self._value.false_value, str
118118
return self.value, self.type
119119

120120

src/ansys/dyna/core/lib/kwd_line_formatter.py

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import typing
2525
import warnings
2626

27+
from ansys.dyna.core.lib.field import Flag
2728
from ansys.dyna.core.lib.parameters import ParameterSet
2829

2930

@@ -83,11 +84,19 @@ def buffer_to_lines(buf: typing.TextIO, max_num_lines: int = -1) -> typing.List[
8384
return data_lines
8485

8586

87+
def _is_flag(item_type: typing.Union[type, Flag]):
88+
if isinstance(item_type, Flag):
89+
return True
90+
return False
91+
92+
8693
def _expand_spec(spec: typing.List[tuple]) -> typing.List[tuple]:
8794
specs = []
8895
for item in spec:
8996
position, width, item_type = item
90-
if dataclasses.is_dataclass(item_type):
97+
if _is_flag(item_type):
98+
specs.append(item)
99+
elif dataclasses.is_dataclass(item_type):
91100
offset = position
92101
for field in dataclasses.fields(item_type):
93102
item_spec = (offset, width, field.type)
@@ -104,7 +113,9 @@ def _contract_data(spec: typing.List[tuple], data: typing.List) -> typing.Iterab
104113
while True:
105114
try:
106115
_, _, item_type = next(iterspec)
107-
if dataclasses.is_dataclass(item_type):
116+
if _is_flag(item_type):
117+
yield next(iterdata)
118+
elif dataclasses.is_dataclass(item_type):
108119
args = [next(iterdata) for f in dataclasses.fields(item_type)]
109120
yield item_type(*args)
110121
else:
@@ -116,6 +127,7 @@ def _contract_data(spec: typing.List[tuple], data: typing.List) -> typing.Iterab
116127
def load_dataline(spec: typing.List[tuple], line_data: str, parameter_set: ParameterSet = None) -> typing.List:
117128
"""loads a keyword card line with fixed column offsets and width from string
118129
spec: list of tuples representing the (offset, width, type) of each field
130+
type can be a Flag which represents the True and False value
119131
line_data: string with keyword data
120132
example:
121133
>>> load_dataline([(0,10, int),(10,10, str)], ' 1 hello')
@@ -144,6 +156,14 @@ def has_value(text_block: str) -> bool:
144156
def get_none_value(item_type):
145157
if item_type is float:
146158
return float("nan")
159+
if _is_flag(item_type):
160+
if len(item_type.false_value) == 0:
161+
return False
162+
if len(item_type.true_value) == 0:
163+
return True
164+
raise Exception(
165+
"No input data for flag. Expected true or false value because neither uses `no input` as a value!"
166+
)
147167
return None
148168

149169
def has_parameter(text_block: str) -> bool:
@@ -171,6 +191,21 @@ def get_parameter(text_block: str, item_type: type) -> typing.Any:
171191
end_position, text_block = seek_text_block(line_data, position, width)
172192
if not has_value(text_block):
173193
value = get_none_value(item_type)
194+
elif _is_flag(item_type):
195+
flag: Flag = item_type
196+
true_value = flag.true_value
197+
false_value = flag.false_value
198+
# check the true value first, empty text may be false but not true
199+
if true_value in text_block:
200+
value = True
201+
else:
202+
if len(false_value) == 0:
203+
warnings.warn("value detected in field where false value was an empty string")
204+
value = False
205+
else:
206+
if false_value in text_block:
207+
value = False
208+
raise Exception("Failed to find true or false value in flag")
174209
elif has_parameter(text_block):
175210
assert parameter_set != None
176211
value = get_parameter(text_block, item_type)
@@ -187,6 +222,5 @@ def get_parameter(text_block: str, item_type: type) -> typing.Any:
187222
if end_position < len(line_data):
188223
warning_message = f'Detected out of bound card characters:\n"{line_data[end_position:]}"\n"Ignoring.'
189224
warnings.warn(warning_message)
190-
191225
data = list(_contract_data(spec, data))
192226
return tuple(data)

src/ansys/dyna/core/lib/option_card.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ def __repr__(self) -> str:
223223
for option_spec in option_specs:
224224
active = self._api.is_option_active(option_spec.name)
225225
active_string = "active" if active else "not active"
226-
sio.write(f"\n {option_name} option is {active_string}.")
226+
sio.write(f"\n {option_spec.name} option is {active_string}.")
227227
return sio.getvalue()
228228

229229
@property

0 commit comments

Comments
 (0)