Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions src/ansys/dpf/core/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

from ansys import dpf
from ansys.dpf.core import dimensionality, errors, meshed_region, scoping, time_freq_support
from ansys.dpf.core.available_result import Homogeneity
from ansys.dpf.core.common import (
_get_size_of_list,
locations,
Expand Down Expand Up @@ -617,12 +618,18 @@
return self.field_definition.unit

@unit.setter
def unit(self, value):
def unit(self, value: str | tuple[Homogeneity, str]):
"""Change the unit for the field.

A single string is interpreted as a known physical unit with an associated homogeneity.

For DPF 11.0 (2026 R1) and above: A tuple of two strings is interpreted as a homogeneity and a unit name.
If the homogeneity is :py:attr:`Homogeneity.dimensionless`, then the unit string is kept as a name.
Otherwise, the homogeneity is ignored, and the unit string interpreted as a known physical unit with an associated homogeneity.

Parameters
----------
value : str
value:
Units for the field.

Examples
Expand All @@ -635,10 +642,24 @@
>>> my_field.unit
'm'


Named dimensionless unit.

>>> from ansys.dpf import core as dpf
>>> from ansys.dpf.core.available_result import Homogeneity
>>> my_field = dpf.Field(10)
>>> my_field.unit = (Homogeneity.dimensionless, "dollars")
>>> print(my_field.unit)
'dollars'

Notes
-----
Setting a named dimensionless unit requires DPF 11.0 (2026 R1) or above.

"""
fielddef = self.field_definition
fielddef.unit = value
self.field_definition = fielddef
field_def = self.field_definition
field_def.unit = value
self.field_definition = field_def

Check warning on line 662 in src/ansys/dpf/core/field.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/dpf/core/field.py#L660-L662

Added lines #L660 - L662 were not covered by tests

@property
def dimensionality(self):
Expand Down
47 changes: 44 additions & 3 deletions src/ansys/dpf/core/field_definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@

"""FieldDefinition."""

from __future__ import annotations

import traceback
import warnings

from ansys.dpf.core import server as server_module
from ansys.dpf.core.check_version import version_requires
from ansys.dpf.core.available_result import Homogeneity
from ansys.dpf.core.check_version import server_meet_version_and_raise, version_requires
from ansys.dpf.core.common import natures, shell_layers
from ansys.dpf.core.dimensionality import Dimensionality
from ansys.dpf.gate import (
Expand Down Expand Up @@ -204,8 +207,46 @@
return is_of_quantity_type

@unit.setter
def unit(self, value):
self._api.csfield_definition_set_unit(self, value, None, 0, 0, 0)
def unit(self, value: str | tuple[Homogeneity, str]):
"""Change the unit for the field definition.
A single string is interpreted as a known physical unit with an associated homogeneity.
For DPF 11.0 (2026 R1) and above: A tuple of two strings is interpreted as a homogeneity and a unit name.
If the homogeneity is :py:attr:`Homogeneity.dimensionless`, then the unit string is kept as a name.
Otherwise, the homogeneity is ignored, and the unit string interpreted as a known physical unit with an associated homogeneity.
Parameters
----------
value:
Units for the field.
Notes
-----
Setting a named dimensionless unit requires DPF 11.0 (2026 R1) or above.
"""
# setter with explicit homogeneity: homogeneity is taken into account if it is dimensionless
if (

Check warning on line 230 in src/ansys/dpf/core/field_definition.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/dpf/core/field_definition.py#L230

Added line #L230 was not covered by tests
isinstance(value, tuple)
and len(value) == 2
and isinstance(value[0], Homogeneity)
and isinstance(value[1], str)
):
server_meet_version_and_raise(

Check warning on line 236 in src/ansys/dpf/core/field_definition.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/dpf/core/field_definition.py#L236

Added line #L236 was not covered by tests
required_version="11.0",
server=self._server,
msg="Setting a named dimensionless unit requires DPF 11.0 (2026 R1) or above.",
)
# csfield_definition_set_unit will ignore the homogeneity if it is not dimensionless
self._api.csfield_definition_set_unit(self, value[1], None, value[0].value, 0, 0)

Check warning on line 242 in src/ansys/dpf/core/field_definition.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/dpf/core/field_definition.py#L242

Added line #L242 was not covered by tests
# standard unit setter, using string interpreter
elif isinstance(value, str):
self._api.csfield_definition_set_unit(self, value, None, 0, 0, 0)

Check warning on line 245 in src/ansys/dpf/core/field_definition.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/dpf/core/field_definition.py#L244-L245

Added lines #L244 - L245 were not covered by tests
else:
raise ValueError(

Check warning on line 247 in src/ansys/dpf/core/field_definition.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/dpf/core/field_definition.py#L247

Added line #L247 was not covered by tests
"Unit setter supports either string or tuple(Homogeneity, str)"
)

@location.setter
def location(self, value):
Expand Down
33 changes: 32 additions & 1 deletion tests/test_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,16 @@
from ansys import dpf
from ansys.dpf import core
from ansys.dpf.core import FieldDefinition, operators as ops
from ansys.dpf.core.available_result import Homogeneity
from ansys.dpf.core.check_version import server_meet_version
from ansys.dpf.core.common import locations, shell_layers
from ansys.dpf.gate.errors import DPFServerException, DpfVersionNotSupported
import conftest
from conftest import SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_8_0, running_docker
from conftest import (
SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_8_0,
raises_for_servers_version_under,
running_docker,
)


@pytest.fixture()
Expand Down Expand Up @@ -1417,3 +1423,28 @@ def test_deep_copy_big_field_remote(server_type, server_type_remote_process):

out = dpf.core.core._deep_copy(field_a, server_type_remote_process)
assert np.allclose(out.data, data)


def test_set_units(server_type):
data = np.random.random(100)
field = dpf.core.field_from_array(data)
# use string setter with recognized string
field.unit = "m"
assert field.unit == "m"

if server_meet_version("11.0", server_type):
# use tuple(Homogeneity, string) setter
field.unit = (Homogeneity.dimensionless, "sones")
assert field.unit == "sones"
else:
with pytest.raises(DpfVersionNotSupported):
# use tuple(Homogeneity, string) setter
field.unit = (Homogeneity.dimensionless, "sones")

# use unrecognized string
with pytest.raises(DPFServerException):
field.unit = "sones"

# use wrong type of arguments
with pytest.raises(ValueError):
field.unit = 1.0
Loading