Unyt module for python - how to use correctly .simplify()?

18 views Asked by At

I am using Unyt module for python and found unexpected, resp. "unintuitive" results.

In simple code I tried to brake down problem.

What I am trying to achieve:

a = 23\*kN/m

b = N/m

c = a/b = (23\*kN/m) / (N/m) =  23000 #dimensionless

I have found solution, which is giving me desired results, I just doubt if the approach is correct.

Code:

import unyt as u
from unyt import m, kN, N


a = 23*kN/m
b = N/m
c = a/b

print(f"{type(a) = }")
print(f"{type(b) = }")
print(f"{type(c) = } \n")

print(f"{c = } \n")
# Expected 'unyt_quantity(23000, 'dimensionless')', got 'unyt_quantity(23, 'kN/N')'
# Well technically true


print(f"{c.units = } \n")
# Expected 'dimensionless', got 'kN/N' - technically true


print(f"{c.units.simplify() = }") # Expected 1000, got 1000
print(f"{c = } \n")
# Expected 'unyt_quantity(23000, 'dimensionless')', got 'unyt_quantity(23, '1000')'


# After .simplify() units get obviously altered permanently
# from 'unyt_quantity(23000, 'kN/N') to 'unyt_quantity(23, '1000')


print(f"{c*c.units.simplify() = } \n")
# Not intuitive result, but after logic above, it is actualy:
# 23 * unit(1000) * unit(1000) = 23*unit(1000000)


print(f"{c.v*c.units.simplify() = } \n")
# Again, results are ok, but not expected from math/intuitive point of view
# >>> c.v*c.units.simplify() = unyt_quantity(23, '1000')


print(f"{float(str(c.units.simplify()))*c.v = }")
# This is giving results I am searching for, but feels more as workaround,
# rather than correct approach

"""
Expected math approach:
c = a / b
c = (23 * kN/m) / (N/m)
c = (23 * 1000*N/m) / (N/m)
c = 23000 * (N/m) / (N/m)
c = 23000 * 1/1
c = 23000
"""

Output:

type(a) = <class 'unyt.array.unyt_quantity'>
type(b) = <class 'unyt.unit_object.Unit'>
type(c) = <class 'unyt.array.unyt_quantity'> 

c = unyt_quantity(23, 'kN/N') 

c.units = kN/N 

c.units.simplify() = 1000
c = unyt_quantity(23, '1000') 

c*c.units.simplify() = unyt_quantity(23, '1000000') 

c.v*c.units.simplify() = unyt_quantity(23, '1000') 

float(str(c.units.simplify()))*c.v = 23000.0

If I use float(str(c.units.simplify()))*c.v, it will give me solution I am searching for, but I doubt that it is correct approach.

Also I do already understand, that c.units.simplify() is resulting in 1000 as unit and not number, therefor, any number multiplication is result of "number '1000'" and not "number×1000".

If there is someone, who understand better way, I would be more than happy for such help.

1

There are 1 answers

0
Robert On

As far as I understand, the problem is, that variable b = N/m is considered as <class 'unyt.unit_object.Unit'> and not <class 'unyt.array.unyt_quantity'>.

Therefore, c = a/b resulting in 23 kN/N seems unexpected, but is indeed correct.

Rewriting code to:

import unyt as u
from unyt import m, kN, N


a = 23*kN/m
b = 1 * N/m # <<< added number, so b is unyt_quantity
c = a/b

or

a = 23*kN/m
b = N/m
c = a/(1*b) # deviding by <unyt_quantity = (1*b)>

will result in 23000 dimensionless.

If we use afterwards:

c.v
# or
c.value

It will give desired result of 23000.

To fully answer the question, best approach is to ensure that same <class 'unyt.array.unyt_quantity'> classes are used for math computing and not being confused with <class 'unyt.unit_object.Unit'>.