Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Arithmetical operations between unit systems are not commutative for user defined units #148

Open
Xarthisius opened this issue Mar 17, 2020 · 5 comments

Comments

@Xarthisius
Copy link
Member

  • unyt version: 2.7.1
  • Python version: 3.6
  • Operating System: Ubuntu 18.04

Description

Order of operations (addition or multiplication) on quantities using two different unit systems for user defined units works only if user defined unit is used first.

As an example:

from unyt.unit_registry import *
from unyt.dimensions import dimensionless
from unyt.array import unyt_quantity

G = unyt_quantity(6.67384e-8, 'cm**3/g/s**2')

default_unit_registry = UnitRegistry(unit_system='cgs')
default_unit_registry.add('h', 1.0, dimensionless, tex_repr=r"h")

print(unyt_quantity(1, "Msun*h", default_unit_registry) * G)  # works
print(G * unyt_quantity(1, "Msun*h", default_unit_registry))  # fails

yields

1.32703693031024e+26 cm**3*h/s**2
Traceback (most recent call last):
  File "/home/xarth/codes/yt-project/unyt/unyt/unit_registry.py", line 72, in __getitem__
    ret = self.lut[str(key)]
KeyError: 'h'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/xarth/codes/yt-project/unyt/unyt/unit_registry.py", line 75, in __getitem__
    _lookup_unit_symbol(str(key), self.lut)
  File "/home/xarth/codes/yt-project/unyt/unyt/unit_registry.py", line 331, in _lookup_unit_symbol
    "Could not find unit symbol '%s' in the provided " "symbols." % symbol_str
unyt.exceptions.UnitParseError: Could not find unit symbol 'h' in the provided symbols.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "ala.py", line 11, in <module>
    print(G * unyt_quantity(1, "Msun*h", default_unit_registry))
  File "/home/xarth/codes/yt-project/unyt/unyt/array.py", line 1751, in __array_ufunc__
    mul, unit = unit_operator(u0, u1)
  File "/home/xarth/codes/yt-project/unyt/unyt/array.py", line 163, in _multiply_units
    ret = (unit1 * unit2).simplify()
  File "/home/xarth/codes/yt-project/unyt/unyt/unit_object.py", line 732, in simplify
    self.expr = _cancel_mul(expr, self.registry)
  File "/home/xarth/codes/yt-project/unyt/unyt/unit_object.py", line 767, in _cancel_mul
    u1 = _create_unit_from_factor(pair[0], registry)
  File "/home/xarth/codes/yt-project/unyt/unyt/unit_object.py", line 756, in _create_unit_from_factor
    f = registry[str(base)]
  File "/home/xarth/codes/yt-project/unyt/unyt/unit_registry.py", line 79, in __getitem__
    "The symbol '%s' does not exist in this registry." % key
unyt.exceptions.SymbolNotFoundError: The symbol 'h' does not exist in this registry.
@ngoldbaum
Copy link
Member

Just a head’s up that I’m taking time off from code development, if you all need this fixed for yt then a PR implementing a fix would be probably the quickest way to get a fix merged.

@ngoldbaum
Copy link
Member

Also from what I remember we did add h to yt’s default unit symbol table. In yt are you importing units from yt.units or from unyt directly? Keep in mind that yt.units and unyt have different units defined in their default namespaces. If you are getting this error despite inporting things from yt.units that seems incorrect to me, and might be a hint towars the source of the real issue.

@Xarthisius
Copy link
Member Author

h is just one example of many similar failures. Here yt-project/yt#2487 it was code_pressure. I'm pretty sure we're importing from yt.units, but why does it matter if we can reproduce the behavior outside of yt?

@ngoldbaum
Copy link
Member

Well the example you used was with h...

Would the same issue not happen with yt.units on the current master branch, I would think that even before unyt both sides would need to have the dataset’s unit registry to know about code_pressure.

The reason I’m pushing back on this a bit is because it might be expensive to first check if the unit exists in the registry (a PR and benchmarks proving otherwise would change me mind though) and I think we were happy to work around that with yt.units. Could be wrong though, haven’t explicitly checked.

@matthewturk
Copy link
Member

Hey, glad you're taking some time off. This suggestion has given me something to look into, so I'm trying to take a crack at it here before asking for anything else -- the issue we are actually seeing is the code_pressure symbol missing, and I'll either have a fix I issue a PR to yt or one that I issue here.

Enjoy your time away!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants