def scale(base, kind, prefixes="", multiplier=1): """ Define a scale of similar quantities. """ base, abbrev = base.split('/') res = [] for prefix in ['', *prefixes]: q = Quantity(_names[prefix] + base, abbrev=abbrev) q.set_dimension(kind[0]) q.set_scale_factor(multiplier * _factor[prefix] * kind[1]) res.append(q) return res if prefixes else res[0]
def derive_unit(expr, name=None): """Derive SI-unit from an expression, omitting scale factors.""" from essm.variables import Variable from essm.variables.utils import extract_variables from sympy.physics.units import Dimension from sympy.physics.units.dimensions import dimsys_SI variables = extract_variables(expr) for var1 in variables: q1 = Quantity('q_' + str(var1)) q1.set_dimension( Dimension(Quantity.get_dimensional_expr(var1.definition.unit))) q1.set_scale_factor(var1.definition.unit) expr = expr.xreplace({var1: q1}) dim = Dimension(Quantity.get_dimensional_expr(expr)) return functools.reduce( operator.mul, (SI_DIMENSIONS[d]**p for d, p in dimsys_SI.get_dimensional_dependencies(dim).items()), 1)
def test_prefix_operations(): m = PREFIXES['m'] k = PREFIXES['k'] M = PREFIXES['M'] dodeca = Prefix('dodeca', 'dd', 1, base=12) assert m * k == 1 assert k * k == M assert 1 / m == k assert k / m == M assert dodeca * dodeca == 144 assert 1 / dodeca == S.One / 12 assert k / dodeca == S(1000) / 12 assert dodeca / dodeca == 1 m = Quantity("fake_meter") m.set_dimension(S.One) m.set_scale_factor(S.One) assert dodeca * m == 12 * m assert dodeca / m == 12 / m expr1 = kilo * 3 assert isinstance(expr1, Mul) assert (expr1).args == (3, kilo) expr2 = kilo * x assert isinstance(expr2, Mul) assert (expr2).args == (x, kilo) expr3 = kilo / 3 assert isinstance(expr3, Mul) assert (expr3).args == (Rational(1, 3), kilo) assert (expr3).args == (S.One / 3, kilo) expr4 = kilo / x assert isinstance(expr4, Mul) assert (expr4).args == (1 / x, kilo)
def test_prefix_operations(): m = PREFIXES['m'] k = PREFIXES['k'] M = PREFIXES['M'] dodeca = Prefix('dodeca', 'dd', 1, base=12) assert m * k == 1 assert k * k == M assert 1 / m == k assert k / m == M assert dodeca * dodeca == 144 assert 1 / dodeca == S(1) / 12 assert k / dodeca == S(1000) / 12 assert dodeca / dodeca == 1 m = Quantity("fake_meter") m.set_dimension(S.One) m.set_scale_factor(S.One) assert dodeca * m == 12 * m assert dodeca / m == 12 / m expr1 = kilo * 3 assert isinstance(expr1, Mul) assert (expr1).args == (3, kilo) expr2 = kilo * x assert isinstance(expr2, Mul) assert (expr2).args == (x, kilo) expr3 = kilo / 3 assert isinstance(expr3, Mul) assert (expr3).args == (S(1)/3, kilo) expr4 = kilo / x assert isinstance(expr4, Mul) assert (expr4).args == (1/x, kilo)
def test_prefix_unit(): m = Quantity("fake_meter", abbrev="m") m.set_dimension(length) m.set_scale_factor(1) pref = {"m": PREFIXES["m"], "c": PREFIXES["c"], "d": PREFIXES["d"]} q1 = Quantity("millifake_meter", abbrev="mm") q2 = Quantity("centifake_meter", abbrev="cm") q3 = Quantity("decifake_meter", abbrev="dm") q1.set_dimension(length) q1.set_dimension(length) q1.set_dimension(length) q1.set_scale_factor(PREFIXES["m"]) q1.set_scale_factor(PREFIXES["c"]) q1.set_scale_factor(PREFIXES["d"]) res = [q1, q2, q3] prefs = prefix_unit(m, pref) assert set(prefs) == set(res) assert set(map(lambda x: x.abbrev, prefs)) == set(symbols("mm,cm,dm"))
import operator as op from lark import Lark, InlineTransformer from sympy import S from sympy.physics import units from sympy.physics.units import Quantity from sympy.physics.units.dimensions import dimsys_SI from sidekick import namespace DIMENSIONLESS = Quantity("dimensionless") DIMENSIONLESS.set_dimension(S.One) DIMENSIONLESS.set_scale_factor(S.One) SIMPY_UNITS = {k: v for k, v in vars(units).items() if not k.startswith('_')} UNITS = namespace(**SIMPY_UNITS, ) grammar = Lark(r""" ?start : expr | NUMBER -> dimensionless ?expr : expr "*" atom -> mul | expr atom -> mul | expr "/" atom -> div | atom ?atom : name "^" number -> pow | name number -> pow | name name : NAME number : NUMBER