Skip to content

Commit 7d4d780

Browse files
authored
Merge branch 'master' into fix_mode_frequency_value_1699
2 parents 2158efb + 598f64a commit 7d4d780

File tree

6 files changed

+114
-17
lines changed

6 files changed

+114
-17
lines changed

examples/02-modal_analyses/01-plot_and_animate_modes.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,6 @@
7272
# To suppress window pop-up, set the `off_screen` argument to True.
7373
# ~~~~~~~~~~~~~~~~~~~~
7474

75-
animation.animate_mode(disp, mode_number=1, save_as="tmp.gif", off_screen=True)
75+
animation.animate_mode(
76+
disp, mode_number=1, save_as="tmp.gif", off_screen=True, deform_scale_factor=10.0
77+
)

src/ansys/dpf/core/data_sources.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from __future__ import annotations
2626

2727
import os
28-
from pathlib import Path
28+
from pathlib import Path, PurePosixPath, PureWindowsPath
2929
import traceback
3030
from typing import TYPE_CHECKING, Union
3131
import warnings
@@ -159,7 +159,9 @@ def set_result_file_path(
159159
['...tmp...file.rst']
160160
161161
"""
162-
filepath = Path(filepath)
162+
filepath = (
163+
PurePosixPath(filepath) if self._server.os == "posix" else PureWindowsPath(filepath)
164+
)
163165
extension = filepath.suffix
164166
# Handle .res files from CFX
165167
if key == "" and extension == ".res":
@@ -290,7 +292,7 @@ def set_domain_result_file_path(
290292
>>> my_data_sources.set_domain_result_file_path(path='/tmp/file1.rst', key='rst', domain_id=1)
291293
292294
"""
293-
path = Path(path)
295+
path = PurePosixPath(path) if self._server.os == "posix" else PureWindowsPath(path)
294296
if key:
295297
self._api.data_sources_set_domain_result_file_path_with_key_utf8(
296298
self, str(path), key, domain_id
@@ -341,7 +343,9 @@ def add_file_path(
341343
# The filename needs to be a fully qualified file name
342344
# if not os.path.dirname(filepath)
343345

344-
filepath = Path(filepath)
346+
filepath = (
347+
PurePosixPath(filepath) if self._server.os == "posix" else PureWindowsPath(filepath)
348+
)
345349
if not filepath.parent.name:
346350
# append local path
347351
filepath = Path.cwd() / filepath.name
@@ -391,7 +395,9 @@ def add_domain_file_path(
391395
392396
"""
393397
# The filename needs to be a fully qualified file name
394-
filepath = Path(filepath)
398+
filepath = (
399+
PurePosixPath(filepath) if self._server.os == "posix" else PureWindowsPath(filepath)
400+
)
395401
if not filepath.parent.name:
396402
# append local path
397403
filepath = Path.cwd() / filepath.name
@@ -424,7 +430,9 @@ def add_file_path_for_specified_result(
424430
The default is ``""``, in which case the key is found directly.
425431
"""
426432
# The filename needs to be a fully qualified file name
427-
filepath = Path(filepath)
433+
filepath = (
434+
PurePosixPath(filepath) if self._server.os == "posix" else PureWindowsPath(filepath)
435+
)
428436
if not filepath.parent.name:
429437
# append local path
430438
filepath = Path.cwd() / filepath.name

src/ansys/dpf/core/field.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
from ansys import dpf
3232
from ansys.dpf.core import dimensionality, errors, meshed_region, scoping, time_freq_support
33+
from ansys.dpf.core.available_result import Homogeneity
3334
from ansys.dpf.core.common import (
3435
_get_size_of_list,
3536
locations,
@@ -617,12 +618,18 @@ def unit(self):
617618
return self.field_definition.unit
618619

619620
@unit.setter
620-
def unit(self, value):
621+
def unit(self, value: str | tuple[Homogeneity, str]):
621622
"""Change the unit for the field.
622623
624+
A single string is interpreted as a known physical unit with an associated homogeneity.
625+
626+
For DPF 11.0 (2026 R1) and above: A tuple of two strings is interpreted as a homogeneity and a unit name.
627+
If the homogeneity is :py:attr:`Homogeneity.dimensionless`, then the unit string is kept as a name.
628+
Otherwise, the homogeneity is ignored, and the unit string interpreted as a known physical unit with an associated homogeneity.
629+
623630
Parameters
624631
----------
625-
value : str
632+
value:
626633
Units for the field.
627634
628635
Examples
@@ -635,10 +642,24 @@ def unit(self, value):
635642
>>> my_field.unit
636643
'm'
637644
645+
646+
Named dimensionless unit.
647+
648+
>>> from ansys.dpf import core as dpf
649+
>>> from ansys.dpf.core.available_result import Homogeneity
650+
>>> my_field = dpf.Field(10)
651+
>>> my_field.unit = (Homogeneity.dimensionless, "dollars")
652+
>>> print(my_field.unit)
653+
'dollars'
654+
655+
Notes
656+
-----
657+
Setting a named dimensionless unit requires DPF 11.0 (2026 R1) or above.
658+
638659
"""
639-
fielddef = self.field_definition
640-
fielddef.unit = value
641-
self.field_definition = fielddef
660+
field_def = self.field_definition
661+
field_def.unit = value
662+
self.field_definition = field_def
642663

643664
@property
644665
def dimensionality(self):

src/ansys/dpf/core/field_definition.py

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@
2222

2323
"""FieldDefinition."""
2424

25+
from __future__ import annotations
26+
2527
import traceback
2628
import warnings
2729

2830
from ansys.dpf.core import server as server_module
29-
from ansys.dpf.core.check_version import version_requires
31+
from ansys.dpf.core.available_result import Homogeneity
32+
from ansys.dpf.core.check_version import server_meet_version_and_raise, version_requires
3033
from ansys.dpf.core.common import natures, shell_layers
3134
from ansys.dpf.core.dimensionality import Dimensionality
3235
from ansys.dpf.gate import (
@@ -204,8 +207,44 @@ def is_of_quantity_type(self, quantity_type):
204207
return is_of_quantity_type
205208

206209
@unit.setter
207-
def unit(self, value):
208-
self._api.csfield_definition_set_unit(self, value, None, 0, 0, 0)
210+
def unit(self, value: str | tuple[Homogeneity, str]):
211+
"""Change the unit for the field definition.
212+
213+
A single string is interpreted as a known physical unit with an associated homogeneity.
214+
215+
For DPF 11.0 (2026 R1) and above: A tuple of two strings is interpreted as a homogeneity and a unit name.
216+
If the homogeneity is :py:attr:`Homogeneity.dimensionless`, then the unit string is kept as a name.
217+
Otherwise, the homogeneity is ignored, and the unit string interpreted as a known physical unit with an associated homogeneity.
218+
219+
Parameters
220+
----------
221+
value:
222+
Units for the field.
223+
224+
Notes
225+
-----
226+
Setting a named dimensionless unit requires DPF 11.0 (2026 R1) or above.
227+
228+
"""
229+
# setter with explicit homogeneity: homogeneity is taken into account if it is dimensionless
230+
if (
231+
isinstance(value, tuple)
232+
and len(value) == 2
233+
and isinstance(value[0], Homogeneity)
234+
and isinstance(value[1], str)
235+
):
236+
server_meet_version_and_raise(
237+
required_version="11.0",
238+
server=self._server,
239+
msg="Setting a named dimensionless unit requires DPF 11.0 (2026 R1) or above.",
240+
)
241+
# csfield_definition_set_unit will ignore the homogeneity if it is not dimensionless
242+
self._api.csfield_definition_set_unit(self, value[1], None, value[0].value, 0, 0)
243+
# standard unit setter, using string interpreter
244+
elif isinstance(value, str):
245+
self._api.csfield_definition_set_unit(self, value, None, 0, 0, 0)
246+
else:
247+
raise ValueError("Unit setter supports either string or tuple(Homogeneity, str)")
209248

210249
@location.setter
211250
def location(self, value):

src/ansys/dpf/core/model.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,11 +429,11 @@ def streams_provider(self):
429429
return self._stream_provider
430430

431431
def _set_data_sources(self, var_inp):
432-
from pathlib import Path
432+
from pathlib import PurePath
433433

434434
if isinstance(var_inp, dpf.core.DataSources):
435435
self._data_sources = var_inp
436-
elif isinstance(var_inp, (str, Path)):
436+
elif isinstance(var_inp, (str, PurePath)):
437437
self._data_sources = DataSources(var_inp, server=self._server)
438438
else:
439439
self._data_sources = DataSources(server=self._server)

tests/test_field.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@
2929
from ansys import dpf
3030
from ansys.dpf import core
3131
from ansys.dpf.core import FieldDefinition, operators as ops
32+
from ansys.dpf.core.available_result import Homogeneity
3233
from ansys.dpf.core.check_version import server_meet_version
3334
from ansys.dpf.core.common import locations, shell_layers
35+
from ansys.dpf.gate.errors import DPFServerException, DpfVersionNotSupported
3436
import conftest
3537
from conftest import SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_8_0, running_docker
3638

@@ -1417,3 +1419,28 @@ def test_deep_copy_big_field_remote(server_type, server_type_remote_process):
14171419

14181420
out = dpf.core.core._deep_copy(field_a, server_type_remote_process)
14191421
assert np.allclose(out.data, data)
1422+
1423+
1424+
def test_set_units(server_type):
1425+
data = np.random.random(100)
1426+
field = dpf.core.field_from_array(data)
1427+
# use string setter with recognized string
1428+
field.unit = "m"
1429+
assert field.unit == "m"
1430+
1431+
if server_meet_version("11.0", server_type):
1432+
# use tuple(Homogeneity, string) setter
1433+
field.unit = (Homogeneity.dimensionless, "sones")
1434+
assert field.unit == "sones"
1435+
else:
1436+
with pytest.raises(DpfVersionNotSupported):
1437+
# use tuple(Homogeneity, string) setter
1438+
field.unit = (Homogeneity.dimensionless, "sones")
1439+
1440+
# use unrecognized string
1441+
with pytest.raises(DPFServerException):
1442+
field.unit = "sones"
1443+
1444+
# use wrong type of arguments
1445+
with pytest.raises(ValueError):
1446+
field.unit = 1.0

0 commit comments

Comments
 (0)