Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 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 @@ def unit(self):
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 @@ def unit(self, value):
>>> 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

@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 @@ def is_of_quantity_type(self, quantity_type):
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 (
isinstance(value, tuple)
and len(value) == 2
and isinstance(value[0], Homogeneity)
and isinstance(value[1], str)
):
server_meet_version_and_raise(
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)
# standard unit setter, using string interpreter
elif isinstance(value, str):
self._api.csfield_definition_set_unit(self, value, None, 0, 0, 0)
else:
raise ValueError(
None, message="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