Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
1db8640d
Commit
1db8640d
authored
Mar 12, 2011
by
Peter Eastman
Browse files
Further optimizations to units code
parent
ee78f1e7
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
65 additions
and
51 deletions
+65
-51
wrappers/python/simtk/unit/quantity.py
wrappers/python/simtk/unit/quantity.py
+39
-32
wrappers/python/simtk/unit/unit.py
wrappers/python/simtk/unit/unit.py
+17
-18
wrappers/python/simtk/unit/unit_operators.py
wrappers/python/simtk/unit/unit_operators.py
+9
-1
No files found.
wrappers/python/simtk/unit/quantity.py
View file @
1db8640d
...
...
@@ -261,6 +261,8 @@ class Quantity(object):
def
__lt__
(
self
,
other
):
return
self
.
_value
<
(
other
.
value_in_unit
(
self
.
unit
))
_reduce_cache
=
{}
def
reduce_unit
(
self
,
guide_unit
=
None
):
"""
Combine similar component units and scale, to form an
...
...
@@ -268,41 +270,46 @@ class Quantity(object):
Returns underlying value type if unit is dimensionless.
"""
value_factor
=
1.0
canonical_units
=
{}
# dict of dimensionTuple: (Base/ScaledUnit, exponent)
# Bias result toward guide units
if
guide_unit
!=
None
:
for
u
,
exponent
in
guide_unit
.
iter_base_or_scaled_units
():
key
=
(
self
.
unit
,
guide_unit
)
if
key
in
Quantity
.
_reduce_cache
:
(
unit
,
value_factor
)
=
Quantity
.
_reduce_cache
[
key
]
else
:
value_factor
=
1.0
canonical_units
=
{}
# dict of dimensionTuple: (Base/ScaledUnit, exponent)
# Bias result toward guide units
if
guide_unit
!=
None
:
for
u
,
exponent
in
guide_unit
.
iter_base_or_scaled_units
():
d
=
u
.
get_dimension_tuple
()
if
d
not
in
canonical_units
:
canonical_units
[
d
]
=
[
u
,
0
]
for
u
,
exponent
in
self
.
unit
.
iter_base_or_scaled_units
():
d
=
u
.
get_dimension_tuple
()
# Take first unit found in a dimension as canonical
if
d
not
in
canonical_units
:
canonical_units
[
d
]
=
[
u
,
0
]
for
u
,
exponent
in
self
.
unit
.
iter_base_or_scaled_units
():
d
=
u
.
get_dimension_tuple
()
# Take first unit found in a dimension as canonical
if
d
not
in
canonical_units
:
canonical_units
[
d
]
=
[
u
,
exponent
]
canonical_units
[
d
]
=
[
u
,
exponent
]
else
:
value_factor
*=
(
u
.
conversion_factor_to
(
canonical_units
[
d
][
0
])
**
exponent
)
canonical_units
[
d
][
1
]
+=
exponent
new_base_units
=
{}
for
d
in
canonical_units
:
u
,
exponent
=
canonical_units
[
d
]
if
exponent
!=
0
:
assert
u
not
in
new_base_units
new_base_units
[
u
]
=
exponent
# Create new unit
if
len
(
new_base_units
)
==
0
:
unit
=
dimensionless
else
:
value_factor
*=
(
u
.
conversion_factor_to
(
canonical_units
[
d
][
0
])
**
exponent
)
canonical_units
[
d
][
1
]
+=
exponent
new_base_units
=
{}
for
d
in
canonical_units
:
u
,
exponent
=
canonical_units
[
d
]
if
exponent
!=
0
:
assert
u
not
in
new_base_units
new_base_units
[
u
]
=
exponent
# Create new unit
if
len
(
new_base_units
)
==
0
:
unit
=
dimensionless
else
:
unit
=
Unit
(
new_base_units
)
# There might be a factor due to unit conversion, even though unit is dimensionless
# e.g. suppose unit is meter/centimeter
if
unit
.
is_dimensionless
():
unit_factor
=
unit
.
conversion_factor_to
(
dimensionless
)
if
unit_factor
!=
1.0
:
value_factor
*=
unit_factor
# print "value_factor = %s" % value_factor
unit
=
dimensionless
unit
=
Unit
(
new_base_units
)
# There might be a factor due to unit conversion, even though unit is dimensionless
# e.g. suppose unit is meter/centimeter
if
unit
.
is_dimensionless
():
unit_factor
=
unit
.
conversion_factor_to
(
dimensionless
)
if
unit_factor
!=
1.0
:
value_factor
*=
unit_factor
# print "value_factor = %s" % value_factor
unit
=
dimensionless
Quantity
.
_reduce_cache
[
key
]
=
(
unit
,
value_factor
)
# Create Quantity, then scale (in case value is a container)
# That's why we don't just scale the value.
result
=
Quantity
(
self
.
_value
,
unit
)
...
...
wrappers/python/simtk/unit/unit.py
View file @
1db8640d
...
...
@@ -144,19 +144,7 @@ class Unit(object):
def
__eq__
(
self
,
other
):
if
not
is_unit
(
other
):
return
False
if
self
.
_all_base_units
==
other
.
_all_base_units
and
self
.
_scaled_units
==
other
.
_scaled_units
:
return
True
if
hash
(
self
)
!=
hash
(
other
):
return
False
factor
=
1.0
factor
*=
self
.
get_conversion_factor_to_base_units
()
factor
/=
other
.
get_conversion_factor_to_base_units
()
for
(
base1
,
exp1
),
(
base2
,
exp2
)
in
zip
(
self
.
iter_all_base_units
(),
other
.
iter_all_base_units
()):
if
base1
.
dimension
!=
base2
.
dimension
or
exp1
!=
exp2
:
return
False
if
base1
!=
base2
:
factor
*=
base1
.
conversion_factor_to
(
base2
)
**
exp1
return
factor
==
1.0
return
self
.
get_name
()
==
other
.
get_name
()
def
__ne__
(
self
,
other
):
return
not
self
.
__eq__
(
other
)
...
...
@@ -181,10 +169,7 @@ class Unit(object):
return
self
.
_hash
except
AttributeError
:
pass
description
=
""
for
unit
,
power
in
self
.
iter_all_base_units
():
description
+=
unit
.
name
+
str
(
power
)
self
.
_hash
=
hash
(
description
)
self
.
_hash
=
hash
(
self
.
get_name
())
return
self
.
_hash
# def __mul__(self, other):
...
...
@@ -204,15 +189,24 @@ class Unit(object):
# def __rdiv__(self, other):
# Because rdiv returns a Quantity, look in quantity.py for definition of Unit.__rdiv__
_pow_cache
=
{}
def
__pow__
(
self
,
exponent
):
"""Raise a Unit to a power.
Returns a new Unit with different exponents on the BaseUnits.
"""
if
self
in
Unit
.
_pow_cache
:
if
exponent
in
Unit
.
_pow_cache
[
self
]:
return
Unit
.
_pow_cache
[
self
][
exponent
]
else
:
Unit
.
_pow_cache
[
self
]
=
{}
result
=
{}
# dictionary of unit: exponent
for
unit
,
exponent2
in
self
.
iter_base_or_scaled_units
():
result
[
unit
]
=
exponent2
*
exponent
return
Unit
(
result
)
new_unit
=
Unit
(
result
)
Unit
.
_pow_cache
[
self
][
exponent
]
=
new_unit
return
new_unit
def
sqrt
(
self
):
"""
...
...
@@ -419,6 +413,10 @@ class Unit(object):
Returns a unit name (string) for this Unit, composed of its various
BaseUnit symbols. e.g. 'kilogram meter**2 secon**-1'.
"""
try
:
return
self
.
_name
except
AttributeError
:
pass
# emit positive exponents first
pos
=
""
pos_count
=
0
...
...
@@ -456,6 +454,7 @@ class Unit(object):
name
=
"dimensionless"
else
:
name
=
"%s%s"
%
(
pos_string
,
neg_string
)
self
.
_name
=
name
return
name
...
...
wrappers/python/simtk/unit/unit_operators.py
View file @
1db8640d
...
...
@@ -61,6 +61,11 @@ def _unit_class_mul(self, other):
of the Quantity is returned.
"""
if
is_unit
(
other
):
if
self
in
Unit
.
_multiplication_cache
:
if
other
in
Unit
.
_multiplication_cache
[
self
]:
return
Unit
.
_multiplication_cache
[
self
][
other
]
else
:
Unit
.
_multiplication_cache
[
self
]
=
{}
# print "unit * unit"
result1
=
{}
# dictionary of dimensionTuple: (BaseOrScaledUnit, exponent)
for
unit
,
exponent
in
self
.
iter_base_or_scaled_units
():
...
...
@@ -83,7 +88,9 @@ def _unit_class_mul(self, other):
if
exponent
!=
0
:
assert
unit
not
in
result2
result2
[
unit
]
=
exponent
return
Unit
(
result2
)
new_unit
=
Unit
(
result2
)
Unit
.
_multiplication_cache
[
self
][
other
]
=
new_unit
return
new_unit
elif
is_quantity
(
other
):
# print "unit * quantity"
value
=
other
.
_value
...
...
@@ -99,6 +106,7 @@ def _unit_class_mul(self, other):
Unit
.
__mul__
=
_unit_class_mul
Unit
.
__rmul__
=
Unit
.
__mul__
Unit
.
_multiplication_cache
=
{}
# run module directly for testing
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment