Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[HOTFIX] fix(): Amend bugs in PR#668, also changed Imperial unit system to use Fahrenheit as default temperature unit (#678) #680

Merged
Show file tree
Hide file tree
Changes from all 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
57 changes: 12 additions & 45 deletions flow360/component/simulation/unit_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import unyt.dimensions as udim
from pydantic import PlainSerializer
from pydantic_core import InitErrorDetails, core_schema
from sympy import Symbol

from flow360.log import log
from flow360.utils import classproperty
Expand All @@ -35,47 +36,13 @@
udim.mass_flow_rate = udim.mass / udim.time
udim.specific_energy = udim.length**2 * udim.time ** (-2)
udim.frequency = udim.time ** (-1)
udim.delta_temperature = udim.temperature

# pylint: disable=fixme
# TODO: IIRC below is automatically derived once you define things above.
# pylint: disable=no-member
u.unit_systems.mks_unit_system["viscosity"] = u.Pa * u.s
u.unit_systems.mks_unit_system["angular_velocity"] = u.rad / u.s
u.unit_systems.mks_unit_system["heat_flux"] = u.kg / u.s**3
u.unit_systems.mks_unit_system["moment"] = u.N * u.m
u.unit_systems.mks_unit_system["heat_source"] = u.kg / u.s**3 / u.m
u.unit_systems.mks_unit_system["specific_heat_capacity"] = u.m**2 / u.s**2 / u.K
u.unit_systems.mks_unit_system["thermal_conductivity"] = u.kg / u.s**3 * u.m / u.K
u.unit_systems.mks_unit_system["inverse_area"] = u.m ** (-2)
u.unit_systems.mks_unit_system["inverse_length"] = u.m ** (-1)
u.unit_systems.mks_unit_system["delta_temperature"] = u.K

# pylint: disable=no-member
u.unit_systems.cgs_unit_system["viscosity"] = u.dyn * u.s / u.cm**2
u.unit_systems.cgs_unit_system["angular_velocity"] = u.rad / u.s
u.unit_systems.cgs_unit_system["heat_flux"] = u.g / u.s**3
u.unit_systems.cgs_unit_system["moment"] = u.dyn * u.m
u.unit_systems.cgs_unit_system["heat_source"] = u.g / u.s**3 / u.cm
u.unit_systems.cgs_unit_system["specific_heat_capacity"] = u.cm**2 / u.s**2 / u.K
u.unit_systems.cgs_unit_system["thermal_conductivity"] = u.g / u.s**3 * u.cm / u.K
u.unit_systems.cgs_unit_system["inverse_area"] = u.cm ** (-2)
u.unit_systems.cgs_unit_system["inverse_length"] = u.cm ** (-1)
u.unit_systems.cgs_unit_system["delta_temperature"] = u.K

# pylint: disable=no-member
u.unit_systems.imperial_unit_system["viscosity"] = u.lbf * u.s / u.ft**2
u.unit_systems.imperial_unit_system["angular_velocity"] = u.rad / u.s
u.unit_systems.imperial_unit_system["heat_flux"] = u.lb / u.s**3
u.unit_systems.imperial_unit_system["moment"] = u.lbf * u.ft
u.unit_systems.imperial_unit_system["heat_source"] = u.lb / u.s**3 / u.ft
u.unit_systems.imperial_unit_system["specific_heat_capacity"] = u.ft**2 / u.s**2 / u.K
u.unit_systems.imperial_unit_system["thermal_conductivity"] = u.lb / u.s**3 * u.ft / u.K
u.unit_systems.imperial_unit_system["inverse_area"] = u.ft ** (-2)
u.unit_systems.imperial_unit_system["inverse_length"] = u.ft ** (-1)
udim.delta_temperature = Symbol("(delta temperature)", positive=True)

# u.Unit("delta_degF") is parsed by unyt as 'ΔdegF and cannot find the unit. Had to use expr instead.
u.unit_systems.imperial_unit_system["temperature"] = u.Unit("degF").expr
u.unit_systems.imperial_unit_system["delta_temperature"] = u.Unit("delta_degF").expr
u.unit_systems.mks_unit_system["delta_temperature"] = u.Unit("K").expr
u.unit_systems.cgs_unit_system["delta_temperature"] = u.Unit("K").expr


class UnitSystemManager:
Expand Down Expand Up @@ -138,6 +105,7 @@ def _check_if_input_has_delta_unit(quant):
or str(quant.units) == "R" # absolute temperature so it can be considered delta
# Flow360 temperature scaled by absolute temperature, making it also absolute temperature
or str(quant.units) == "flow360_delta_temperature_unit"
or str(quant.units) == "flow360_temperature_unit"
)
return is_input_delta_unit

Expand Down Expand Up @@ -217,9 +185,13 @@ def _unit_inference_validator(value, dim_name, is_array=False):
if is_array:
if all(isinstance(item, Number) for item in value):
float64_tuple = tuple(np.float64(item) for item in value)
return float64_tuple * unit
if isinstance(unit, _Flow360BaseUnit):
return float64_tuple * unit
return float64_tuple * unit.units
if isinstance(value, Number):
return np.float64(value) * unit
if isinstance(unit, _Flow360BaseUnit):
return np.float64(value) * unit
return np.float64(value) * unit.units
return value


Expand Down Expand Up @@ -1774,8 +1746,3 @@ def __get_validators__(cls):
CGS_unit_system = CGSUnitSystem()
imperial_unit_system = ImperialUnitSystem()
flow360_unit_system = Flow360UnitSystem()

# register SI, CGS unit system
u.UnitSystem("SI", "m", "kg", "s")
u.UnitSystem("CGS", "cm", "g", "s")
u.UnitSystem("Imperial", "ft", "lb", "s", temperature_unit="degF")
67 changes: 8 additions & 59 deletions flow360/component/v1/unit_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,63 +34,6 @@
u.dimensions.inverse_area = 1 / u.dimensions.area
u.dimensions.inverse_length = 1 / u.dimensions.length

# pylint: disable=no-member
u.unit_systems.mks_unit_system["viscosity"] = u.Pa * u.s
# pylint: disable=no-member
u.unit_systems.mks_unit_system["angular_velocity"] = u.rad / u.s
# pylint: disable=no-member
u.unit_systems.mks_unit_system["heat_flux"] = u.kg / u.s**3
# pylint: disable=no-member
u.unit_systems.mks_unit_system["moment"] = u.N * u.m
# pylint: disable=no-member
u.unit_systems.mks_unit_system["heat_source"] = u.kg / u.s**3 / u.m
# pylint: disable=no-member
u.unit_systems.mks_unit_system["heat_capacity"] = u.kg / u.s**2 / u.m / u.K
# pylint: disable=no-member
u.unit_systems.mks_unit_system["thermal_conductivity"] = u.kg / u.s**3 * u.m / u.K
# pylint: disable=no-member
u.unit_systems.mks_unit_system["inverse_area"] = u.m ** (-2)
# pylint: disable=no-member
u.unit_systems.mks_unit_system["inverse_length"] = u.m ** (-1)

# pylint: disable=no-member
u.unit_systems.cgs_unit_system["viscosity"] = u.dyn * u.s / u.cm**2
# pylint: disable=no-member
u.unit_systems.cgs_unit_system["angular_velocity"] = u.rad / u.s
# pylint: disable=no-member
u.unit_systems.cgs_unit_system["heat_flux"] = u.g / u.s**3
# pylint: disable=no-member
u.unit_systems.cgs_unit_system["moment"] = u.dyn * u.m
# pylint: disable=no-member
u.unit_systems.cgs_unit_system["heat_source"] = u.g / u.s**3 / u.cm
# pylint: disable=no-member
u.unit_systems.cgs_unit_system["heat_capacity"] = u.g / u.s**2 / u.cm / u.K
# pylint: disable=no-member
u.unit_systems.cgs_unit_system["thermal_conductivity"] = u.g / u.s**3 * u.cm / u.K
# pylint: disable=no-member
u.unit_systems.cgs_unit_system["inverse_area"] = u.cm ** (-2)
# pylint: disable=no-member
u.unit_systems.cgs_unit_system["inverse_length"] = u.cm ** (-1)

# pylint: disable=no-member
u.unit_systems.imperial_unit_system["viscosity"] = u.lbf * u.s / u.ft**2
# pylint: disable=no-member
u.unit_systems.imperial_unit_system["angular_velocity"] = u.rad / u.s
# pylint: disable=no-member
u.unit_systems.imperial_unit_system["heat_flux"] = u.lb / u.s**3
# pylint: disable=no-member
u.unit_systems.imperial_unit_system["moment"] = u.lbf * u.ft
# pylint: disable=no-member
u.unit_systems.imperial_unit_system["heat_source"] = u.lb / u.s**3 / u.ft
# pylint: disable=no-member
u.unit_systems.imperial_unit_system["heat_capacity"] = u.lb / u.s**2 / u.ft / u.K
# pylint: disable=no-member
u.unit_systems.imperial_unit_system["thermal_conductivity"] = u.lb / u.s**3 * u.ft / u.K
# pylint: disable=no-member
u.unit_systems.imperial_unit_system["inverse_area"] = u.ft ** (-2)
# pylint: disable=no-member
u.unit_systems.imperial_unit_system["inverse_length"] = u.ft ** (-1)


class UnitSystemManager:
"""
Expand Down Expand Up @@ -194,13 +137,19 @@ def _unit_inference_validator(value, dim_name, is_array=False):
-------
unyt_quantity or value
"""

if unit_system_manager.current:
unit = unit_system_manager.current[dim_name]
if is_array:
if all(isinstance(item, Number) for item in value):
return value * unit
float64_tuple = tuple(np.float64(item) for item in value)
if isinstance(unit, _Flow360BaseUnit):
return float64_tuple * unit
return float64_tuple * unit.units
if isinstance(value, Number):
return value * unit
if isinstance(unit, _Flow360BaseUnit):
return np.float64(value) * unit
return np.float64(value) * unit.units
return value


Expand Down
113 changes: 57 additions & 56 deletions tests/simulation/framework/test_unit_system_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ def test_flow360_unit_arithmetic():
data.l_arr_nonneg + [1, 1, 1, 1] * u.m


def _assert_exact_same_unyt(input, ref):
assert input.value == ref.value and str(input.units.expr) == str(ref.units.expr)


def test_unit_system():
# No inference outside of context
with pytest.raises(pd.ValidationError):
Expand All @@ -251,20 +255,20 @@ def test_unit_system():
fqc=1234 / u.s,
)

assert data.L == 1 * u.m
assert data.m == 2 * u.kg
assert data.t == 3 * u.s
assert data.T == 300 * u.K
assert data.v == 2 / 3 * u.m / u.s
assert data.A == 6 * u.m * u.m
assert data.F == 4 * u.kg * u.m / u.s**2
assert data.p == 5 * u.Pa
assert data.r == 2 * u.kg / u.m**3
assert data.mu == 3 * u.Pa * u.s
assert data.omega == 5 * u.rad / u.s
assert data.m_dot == 12 * u.kg / u.s
assert data.v_sq == 4 * u.m**2 / u.s**2
assert data.fqc == 1234 / u.s
_assert_exact_same_unyt(data.L, 1 * u.m)
_assert_exact_same_unyt(data.m, 2 * u.kg)
_assert_exact_same_unyt(data.t, 3 * u.s)
_assert_exact_same_unyt(data.T, 300 * u.K)
_assert_exact_same_unyt(data.v, 2 / 3 * u.m / u.s)
_assert_exact_same_unyt(data.A, 6 * u.m * u.m)
_assert_exact_same_unyt(data.F, 4 * u.kg * u.m / u.s**2)
_assert_exact_same_unyt(data.p, 5 * u.Pa)
_assert_exact_same_unyt(data.r, 2 * u.kg / u.m**3)
_assert_exact_same_unyt(data.mu, 3 * u.Pa * u.s)
_assert_exact_same_unyt(data.omega, 5 * u.rad / u.s)
_assert_exact_same_unyt(data.m_dot, 12 * u.kg / u.s)
_assert_exact_same_unyt(data.v_sq, 4 * u.m**2 / u.s**2)
_assert_exact_same_unyt(data.fqc, 1234 / u.s)

# When using a unit system the units can be inferred

Expand All @@ -287,55 +291,54 @@ def test_unit_system():
with u.SI_unit_system:
data = DataWithUnits(**input, a=1 * u.degree, omega=1 * u.radian / u.s)

assert data.L == 1 * u.m
assert data.m == 2 * u.kg
assert data.t == 3 * u.s
assert data.T == 300 * u.K
assert data.v == 2 / 3 * u.m / u.s
assert data.A == 6 * u.m**2
assert data.F == 4 * u.N
assert data.p == 5 * u.Pa
assert data.r == 2 * u.kg / u.m**3
assert data.mu == 3 * u.Pa * u.s
assert data.m_dot == 11 * u.kg / u.s
assert data.v_sq == 123 * u.m**2 / u.s**2
assert data.fqc == 1111 / u.s
_assert_exact_same_unyt(data.L, 1 * u.m)
_assert_exact_same_unyt(data.m, 2 * u.kg)
_assert_exact_same_unyt(data.t, 3 * u.s)
_assert_exact_same_unyt(data.T, 300 * u.K)
_assert_exact_same_unyt(data.v, 2 / 3 * u.m / u.s)
_assert_exact_same_unyt(data.A, 6 * u.m**2)
_assert_exact_same_unyt(data.F, 4 * u.N)
_assert_exact_same_unyt(data.p, 5 * u.Pa)
_assert_exact_same_unyt(data.r, 2 * u.kg / u.m**3)
_assert_exact_same_unyt(data.mu, 3 * u.kg / (u.m * u.s))
_assert_exact_same_unyt(data.m_dot, 11 * u.kg / u.s)
_assert_exact_same_unyt(data.v_sq, 123 * u.J / u.kg)
_assert_exact_same_unyt(data.fqc, 1111 * u.Hz)

# CGS
with u.CGS_unit_system:
data = DataWithUnits(**input, a=1 * u.degree, omega=1 * u.radian / u.s)

assert data.L == 1 * u.cm
assert data.m == 2 * u.g
assert data.t == 3 * u.s
assert data.T == 300 * u.K
assert data.v == 2 / 3 * u.cm / u.s
assert data.A == 6 * u.cm**2
assert data.F == 4 * u.dyne
assert data.p == 5 * u.dyne / u.cm**2
assert data.r == 2 * u.g / u.cm**3
assert data.mu == 3 * u.dyn * u.s / u.cm**2
assert data.m_dot == 11 * u.g / u.s
assert data.v_sq == 123 * u.cm**2 / u.s**2
assert data.fqc == 1111 / u.s
_assert_exact_same_unyt(data.L, 1 * u.cm)
_assert_exact_same_unyt(data.m, 2 * u.g)
_assert_exact_same_unyt(data.t, 3 * u.s)
_assert_exact_same_unyt(data.T, 300 * u.K)
_assert_exact_same_unyt(data.v, 2 / 3 * u.cm / u.s)
_assert_exact_same_unyt(data.A, 6 * u.cm**2)
_assert_exact_same_unyt(data.F, 4 * u.dyne)
_assert_exact_same_unyt(data.p, 5 * u.dyne / u.cm**2)
_assert_exact_same_unyt(data.r, 2 * u.g / u.cm**3)
_assert_exact_same_unyt(data.mu, 3 * u.g / u.s / u.cm)
_assert_exact_same_unyt(data.m_dot, 11 * u.g / u.s)
_assert_exact_same_unyt(data.v_sq, 123 * u.erg / u.g)
_assert_exact_same_unyt(data.fqc, 1111 / u.s)

# Imperial
with u.imperial_unit_system:
data = DataWithUnits(**input, a=1 * u.degree, omega=1 * u.radian / u.s)

assert data.L == 1 * u.ft
assert data.m == 2 * u.lb
assert data.t == 3 * u.s
assert data.T == 300 * u.R
assert data.v == 2 / 3 * u.ft / u.s
assert data.A == 6 * u.ft**2
assert data.F == 4 * u.lbf
assert data.p == 5 * u.lbf / u.ft**2
assert data.r == 2 * u.lb / u.ft**3
assert data.mu == 3 * u.lbf * u.s / u.ft**2
assert data.m_dot == 11 * u.lb / u.s
assert data.v_sq == 123 * u.ft**2 / u.s**2
assert data.fqc == 1111 / u.s
_assert_exact_same_unyt(data.L, 1 * u.ft)
_assert_exact_same_unyt(data.m, 2 * u.lb)
_assert_exact_same_unyt(data.t, 3 * u.s)
_assert_exact_same_unyt(data.T, 300 * u.degF)
_assert_exact_same_unyt(data.v, 2 / 3 * u.ft / u.s)
_assert_exact_same_unyt(data.A, 6 * u.ft**2)
_assert_exact_same_unyt(data.F, 4 * u.lbf)
_assert_exact_same_unyt(data.p, 5 * u.lbf / u.ft**2)
_assert_exact_same_unyt(data.r, 2 * u.lb / u.ft**3)
_assert_exact_same_unyt(data.mu, 3 * u.lb / (u.ft * u.s))
_assert_exact_same_unyt(data.m_dot, 11 * u.lb / u.s)
_assert_exact_same_unyt(data.v_sq, 123 * u.ft**2 / u.s**2)
_assert_exact_same_unyt(data.fqc, 1111 / u.s)

# Flow360
with u.flow360_unit_system:
Expand Down Expand Up @@ -717,8 +720,6 @@ def test_unit_system_init():
"angle": {"value": 1.0, "units": "rad"},
}
us = u.UnitSystem(**unit_system_dict)
print(us)
print(u.SI_unit_system)
assert us == u.SI_unit_system


Expand Down
2 changes: 1 addition & 1 deletion tests/v1/test_unit_system_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def test_unit_system():
assert data.F == 4 * u.lbf
assert data.p == 5 * u.lbf / u.ft**2
assert data.r == 2 * u.lb / u.ft**3
assert data.mu == 3 * u.lbf * u.s / u.ft**2
assert data.mu == 3 * u.lb / (u.ft * u.s)
assert data.omega == 5 * u.rad / u.s

# Flow360
Expand Down
Loading