Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
48 changes: 45 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,15 @@

"""FieldDefinition."""

from __future__ import annotations

from argparse import ArgumentError
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 +208,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 231 in src/ansys/dpf/core/field_definition.py

View check run for this annotation

Codecov / codecov/patch

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

Added line #L231 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 237 in src/ansys/dpf/core/field_definition.py

View check run for this annotation

Codecov / codecov/patch

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

Added line #L237 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 243 in src/ansys/dpf/core/field_definition.py

View check run for this annotation

Codecov / codecov/patch

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

Added line #L243 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 246 in src/ansys/dpf/core/field_definition.py

View check run for this annotation

Codecov / codecov/patch

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

Added lines #L245 - L246 were not covered by tests
else:
raise ArgumentError(

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

View check run for this annotation

Codecov / codecov/patch

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

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

@location.setter
def location(self, value):
Expand Down
3 changes: 3 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,9 @@ def return_ds(server=None):
return return_ds


SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_11_0 = meets_version(
get_server_version(core._global_server()), "11.0"
)
SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_10_0 = meets_version(
get_server_version(core._global_server()), "10.0"
)
Expand Down
35 changes: 34 additions & 1 deletion tests/test_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from argparse import ArgumentError
import copy
import gc

Expand All @@ -29,10 +30,17 @@
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,
SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_11_0,
raises_for_servers_version_under,
running_docker,
)


@pytest.fixture()
Expand Down Expand Up @@ -1417,3 +1425,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(ArgumentError):
field.unit = 1.0
Loading