Exemplo n.º 1
0
def check_dimensions(expr, unit_system="SI"):
    """Return expr if units in addends have the same
    base dimensions, else raise a ValueError."""
    # the case of adding a number to a dimensional quantity
    # is ignored for the sake of SymPy core routines, so this
    # function will raise an error now if such an addend is
    # found.
    # Also, when doing substitutions, multiplicative constants
    # might be introduced, so remove those now

    from sympy.physics.units import UnitSystem
    unit_system = UnitSystem.get_unit_system(unit_system)

    def addDict(dict1, dict2):
        """Merge dictionaries by adding values of common keys and
        removing keys with value of 0."""
        dict3 = {**dict1, **dict2}
        for key, value in dict3.items():
            if key in dict1 and key in dict2:
                dict3[key] = value + dict1[key]
        return {key: val for key, val in dict3.items() if val != 0}

    adds = expr.atoms(Add)
    DIM_OF = unit_system.get_dimension_system().get_dimensional_dependencies
    for a in adds:
        deset = set()
        for ai in a.args:
            if ai.is_number:
                deset.add(())
                continue
            dims = []
            skip = False
            dimdict = {}
            for i in Mul.make_args(ai):
                if i.has(Quantity):
                    i = Dimension(unit_system.get_dimensional_expr(i))
                if i.has(Dimension):
                    dimdict = addDict(dimdict, DIM_OF(i))
                elif i.free_symbols:
                    skip = True
                    break
            dims.extend(dimdict.items())
            if not skip:
                deset.add(tuple(sorted(dims)))
                if len(deset) > 1:
                    raise ValueError(
                        "addends have incompatible dimensions: {}".format(
                            deset))

    # clear multiplicative constants on Dimensions which may be
    # left after substitution
    reps = {}
    for m in expr.atoms(Mul):
        if any(isinstance(i, Dimension) for i in m.args):
            reps[m] = m.func(*[i for i in m.args if not i.is_number])

    return expr.xreplace(reps)
Exemplo n.º 2
0
 def set_scale_factor(self, scale_factor, unit_system="SI"):
     SymPyDeprecationWarning(
         deprecated_since_version="1.5",
         issue=17765,
         feature="Moving method to UnitSystem class",
         useinstead="unit_system.set_quantity_scale_factor or {}.set_global_relative_scale_factor".format(self),
     ).warn()
     from sympy.physics.units import UnitSystem
     unit_system = UnitSystem.get_unit_system(unit_system)
     unit_system.set_quantity_scale_factor(self, scale_factor)
Exemplo n.º 3
0
    def inverse_convert(cls,
                        dim,
                        scale=1,
                        target_units=None,
                        unit_system="SI"):
        """
        depend on sympy 1.5-1.6!!!
        Quick method. Translate ui to other unit.

        Parameters
        ----------
        dim: Dim
            dim
        scale: float
            scale generated before.
        target_units: None or list of sympy.physics.unit
            if None, the target_units is 7 SI units
        unit_system: str
            default is unit_system="SI"

        Returns
        -------
        scale:float

        expr: Expr
        """
        from sympy.physics.units import UnitSystem
        unit_system = UnitSystem.get_unit_system(unit_system)
        if not target_units:
            target_units = unit_system._base_units

        if not isinstance(target_units, (Iterable, Tuple)):
            target_units = [target_units]

        def get_total_scale_factor(expr):
            if isinstance(expr, Mul):
                return reduce(lambda x, y: x * y,
                              [get_total_scale_factor(i) for i in expr.args])
            elif isinstance(expr, Pow):
                return get_total_scale_factor(expr.base)**expr.exp
            elif isinstance(expr, Quantity):
                return unit_system.get_quantity_scale_factor(expr)
            return expr

        sc = scale * Mul.fromiter(
            1 / get_total_scale_factor(u)**p
            for u, p in zip(unit_system._base_units, dim))
        sc = Mul.fromiter(1 / get_total_scale_factor(u)
                          for u in target_units) / sc

        tar = Mul.fromiter(
            (1 / get_total_scale_factor(u) * u) for u in target_units)
        bas = Mul.fromiter((get_total_scale_factor(u))**p
                           for u, p in zip(unit_system._base_units, dim))
        return sc, scale * tar * bas
Exemplo n.º 4
0
 def _collect_factor_and_dimension(expr, unit_system="SI"):
     """Return tuple with scale factor expression and dimension expression."""
     SymPyDeprecationWarning(
         deprecated_since_version="1.5",
         issue=17765,
         feature="This method has been moved to the UnitSystem class.",
         useinstead="unit_system._collect_factor_and_dimension",
     ).warn()
     from sympy.physics.units import UnitSystem
     unit_system = UnitSystem.get_unit_system(unit_system)
     return unit_system._collect_factor_and_dimension(expr)
Exemplo n.º 5
0
 def get_dimensional_expr(expr, unit_system="SI"):
     SymPyDeprecationWarning(
         deprecated_since_version="1.5",
         issue=17765,
         feature="get_dimensional_expr() is now associated with UnitSystem objects. " \
             "The dimensional relations depend on the unit system used.",
         useinstead="unit_system.get_dimensional_expr"
     ).warn()
     from sympy.physics.units import UnitSystem
     unit_system = UnitSystem.get_unit_system(unit_system)
     return unit_system.get_dimensional_expr(expr)
Exemplo n.º 6
0
 def set_dimension(self, dimension, unit_system="SI"):
     sympy_deprecation_warning(
         f"""
         Quantity.set_dimension() is deprecated. Use either
         unit_system.set_quantity_dimension() or
         {self}.set_global_dimension() instead.
         """,
         deprecated_since_version="1.5",
         active_deprecations_target="deprecated-quantity-methods",
     )
     from sympy.physics.units import UnitSystem
     unit_system = UnitSystem.get_unit_system(unit_system)
     unit_system.set_quantity_dimension(self, dimension)
Exemplo n.º 7
0
 def _collect_factor_and_dimension(expr, unit_system="SI"):
     """Return tuple with scale factor expression and dimension expression."""
     sympy_deprecation_warning(
         """
         Quantity._collect_factor_and_dimension() is deprecated. This
         method has been moved to the UnitSystem class. Use
         unit_system._collect_factor_and_dimension(expr) instead.
         """,
         deprecated_since_version="1.5",
         active_deprecations_target="deprecated-quantity-methods",
     )
     from sympy.physics.units import UnitSystem
     unit_system = UnitSystem.get_unit_system(unit_system)
     return unit_system._collect_factor_and_dimension(expr)
Exemplo n.º 8
0
 def get_dimensional_expr(expr, unit_system="SI"):
     sympy_deprecation_warning(
         """
         Quantity.get_dimensional_expr() is deprecated. It is now
         associated with UnitSystem objects. The dimensional relations
         depend on the unit system used. Use
         unit_system.get_dimensional_expr() instead.
         """,
         deprecated_since_version="1.5",
         active_deprecations_target="deprecated-quantity-methods",
     )
     from sympy.physics.units import UnitSystem
     unit_system = UnitSystem.get_unit_system(unit_system)
     return unit_system.get_dimensional_expr(expr)
Exemplo n.º 9
0
    def convert_to(cls, expr, target_units=None, unit_system="SI"):
        """depend on sympy 1.5-1.6!!!"""
        from sympy.physics.units import UnitSystem
        unit_system = UnitSystem.get_unit_system(unit_system)
        if not target_units:
            target_units = unit_system._base_units

        if not isinstance(target_units, (Iterable, Tuple)):
            target_units = [target_units]

        if isinstance(expr, Add):
            raise TypeError("can not be add")

        expr = sympify(expr)

        if not isinstance(expr, Quantity) and expr.has(Quantity):
            expr = expr.replace(
                lambda x: isinstance(x, Quantity),
                lambda x: x.convert_to(target_units, unit_system))

        def get_total_scale_factor(expr0):
            if isinstance(expr0, Mul):
                return reduce(lambda x, y: x * y,
                              [get_total_scale_factor(i) for i in expr0.args])
            elif isinstance(expr0, Pow):
                return get_total_scale_factor(expr0.base)**expr0.exp
            elif isinstance(expr0, Quantity):
                return unit_system.get_quantity_scale_factor(expr0)
            return expr0

        depmat, canon_dim_units = cls._get_conversion_matrix_for_expr(
            expr, target_units, unit_system)
        if depmat is None:
            raise TypeError("There is an invalid character in '%s'" % expr,
                            "the expr must be sympy.physics.unit or number")

        expr_scale_factor = get_total_scale_factor(expr)
        dim_dict = {}
        for u, p in zip(target_units, depmat):
            expr_scale_factor /= get_total_scale_factor(u)**p
            dim_dict["%s" % u] = p

        d = cls(np.array(list(dim_dict.values())))
        d.dim = canon_dim_units
        d.unit = target_units
        return expr_scale_factor, d
Exemplo n.º 10
0
def check_dimensions(expr, unit_system="SI"):
    """Return expr if there are not unitless values added to
    dimensional quantities, else raise a ValueError."""
    # the case of adding a number to a dimensional quantity
    # is ignored for the sake of SymPy core routines, so this
    # function will raise an error now if such an addend is
    # found.
    # Also, when doing substitutions, multiplicative constants
    # might be introduced, so remove those now

    from sympy.physics.units import UnitSystem
    unit_system = UnitSystem.get_unit_system(unit_system)

    adds = expr.atoms(Add)
    DIM_OF = unit_system.get_dimension_system().get_dimensional_dependencies
    for a in adds:
        deset = set()
        for ai in a.args:
            if ai.is_number:
                deset.add(())
                continue
            dims = []
            skip = False
            for i in Mul.make_args(ai):
                if i.has(Quantity):
                    i = Dimension(unit_system.get_dimensional_expr(i))
                if i.has(Dimension):
                    dims.extend(DIM_OF(i).items())
                elif i.free_symbols:
                    skip = True
                    break
            if not skip:
                deset.add(tuple(sorted(dims)))
                if len(deset) > 1:
                    raise ValueError(
                        "addends have incompatible dimensions")

    # clear multiplicative constants on Dimensions which may be
    # left after substitution
    reps = {}
    for m in expr.atoms(Mul):
        if any(isinstance(i, Dimension) for i in m.args):
            reps[m] = m.func(*[
                i for i in m.args if not i.is_number])

    return expr.xreplace(reps)
Exemplo n.º 11
0
def get_kamodo_unit_system():
    """Same as SI but supports anglular frequency"""

    radian = sympy.physics.units.radian
    degree = sympy.physics.units.degree
    si_unit_system = UnitSystem.get_unit_system('SI')
    si_dimension_system = si_unit_system.get_dimension_system()

    angle = Dimension('angle', 'A')

    kamodo_dims = si_dimension_system.extend(
        new_base_dims=(angle, ),
        new_derived_dims=[Dimension('angular_velocity')],
        new_dim_deps={
            Symbol('angular_velocity'): {
                Symbol('angle'): 1,
                Symbol('time'): -1
            }
        })

    kamodo_units = si_unit_system.extend((radian, ), (radian, degree),
                                         dimension_system=kamodo_dims)

    return kamodo_units
Exemplo n.º 12
0
Arquivo: units.py Projeto: mph-/lcapy
    def __init__(self, unit_system="SI"):

        self.unit_system = UnitSystem.get_unit_system(unit_system)
        self.dim_sys = self.unit_system.get_dimension_system()
        self._mapping = {}

        for i in u.__dict__:
            unit = getattr(u, i)
            if not isinstance(unit, u.Quantity):
                continue

            key = self._makekey(unit)

            # Use earlier defined units

            if key not in self._mapping:
                self._mapping[key] = unit

        # Remove entry for no units.
        self._mapping.pop(self._makekey(1))

        # Add entry for S * ohm, etc.
        key = (None, ) * len(key)
        self._mapping[key] = S.One
Exemplo n.º 13
0
def convert_to(expr, target_units, unit_system="SI"):
    """
    Convert ``expr`` to the same expression with all of its units and quantities
    represented as factors of ``target_units``, whenever the dimension is compatible.

    ``target_units`` may be a single unit/quantity, or a collection of
    units/quantities.

    Examples
    ========

    >>> from sympy.physics.units import speed_of_light, meter, gram, second, day
    >>> from sympy.physics.units import mile, newton, kilogram, atomic_mass_constant
    >>> from sympy.physics.units import kilometer, centimeter
    >>> from sympy.physics.units import gravitational_constant, hbar
    >>> from sympy.physics.units import convert_to
    >>> convert_to(mile, kilometer)
    25146*kilometer/15625
    >>> convert_to(mile, kilometer).n()
    1.609344*kilometer
    >>> convert_to(speed_of_light, meter/second)
    299792458*meter/second
    >>> convert_to(day, second)
    86400*second
    >>> 3*newton
    3*newton
    >>> convert_to(3*newton, kilogram*meter/second**2)
    3*kilogram*meter/second**2
    >>> convert_to(atomic_mass_constant, gram)
    1.660539060e-24*gram

    Conversion to multiple units:

    >>> convert_to(speed_of_light, [meter, second])
    299792458*meter/second
    >>> convert_to(3*newton, [centimeter, gram, second])
    300000*centimeter*gram/second**2

    Conversion to Planck units:

    >>> from sympy.physics.units import gravitational_constant, hbar
    >>> convert_to(atomic_mass_constant, [gravitational_constant, speed_of_light, hbar]).n()
    7.62963085040767e-20*gravitational_constant**(-0.5)*hbar**0.5*speed_of_light**0.5

    """
    from sympy.physics.units import UnitSystem
    unit_system = UnitSystem.get_unit_system(unit_system)

    if not isinstance(target_units, (Iterable, Tuple)):
        target_units = [target_units]

    if isinstance(expr, Add):
        return Add.fromiter(
            convert_to(i, target_units, unit_system) for i in expr.args)

    expr = sympify(expr)

    if not isinstance(expr, Quantity) and expr.has(Quantity):
        expr = expr.replace(lambda x: isinstance(x, Quantity),
                            lambda x: x.convert_to(target_units, unit_system))

    def get_total_scale_factor(expr):
        if isinstance(expr, Mul):
            return reduce(lambda x, y: x * y,
                          [get_total_scale_factor(i) for i in expr.args])
        elif isinstance(expr, Pow):
            return get_total_scale_factor(expr.base)**expr.exp
        elif isinstance(expr, Quantity):
            return unit_system.get_quantity_scale_factor(expr)
        return expr

    depmat = _get_conversion_matrix_for_expr(expr, target_units, unit_system)
    if depmat is None:
        return expr

    expr_scale_factor = get_total_scale_factor(expr)
    return expr_scale_factor * Mul.fromiter(
        (1 / get_total_scale_factor(u) * u)**p
        for u, p in zip(target_units, depmat))
Exemplo n.º 14
0
def convert_unit_to(expr,
                    target_units,
                    unit_system=kamodo_unit_system,
                    raise_errors=True):
    """
    Same as sympy.convert_to but accepts equations and allows functions of units to pass

    Convert ``expr`` to the same expression with all of its units and quantities
    represented as factors of ``target_units``, whenever the dimension is compatible.

    ``target_units`` may be a single unit/quantity, or a collection of
    units/quantities.

    Examples
    ========

    >>> from sympy.physics.units import speed_of_light, meter, gram, second, day
    >>> from sympy.physics.units import mile, newton, kilogram, atomic_mass_constant
    >>> from sympy.physics.units import kilometer, centimeter
    >>> from sympy.physics.units import gravitational_constant, hbar
    >>> from sympy.physics.units import convert_to
    >>> convert_to(mile, kilometer)
    25146*kilometer/15625
    >>> convert_to(mile, kilometer).n()
    1.609344*kilometer
    >>> convert_to(speed_of_light, meter/second)
    299792458*meter/second
    >>> convert_to(day, second)
    86400*second
    >>> 3*newton
    3*newton
    >>> convert_to(3*newton, kilogram*meter/second**2)
    3*kilogram*meter/second**2
    >>> convert_to(atomic_mass_constant, gram)
    1.660539060e-24*gram

    Conversion to multiple units:

    >>> convert_to(speed_of_light, [meter, second])
    299792458*meter/second
    >>> convert_to(3*newton, [centimeter, gram, second])
    300000*centimeter*gram/second**2

    Conversion to Planck units:

    >>> from sympy.physics.units import gravitational_constant, hbar
    >>> convert_to(atomic_mass_constant, [gravitational_constant, speed_of_light, hbar]).n()
    7.62963085040767e-20*gravitational_constant**(-0.5)*hbar**0.5*speed_of_light**0.5

    """

    from sympy.physics.units import UnitSystem
    unit_system = UnitSystem.get_unit_system(unit_system)

    if not isinstance(target_units, (Iterable, Tuple)):
        target_units = [target_units]

    if hasattr(expr, 'rhs'):
        return Eq(convert_unit_to(expr.lhs, target_units, unit_system),
                  convert_unit_to(expr.rhs, target_units, unit_system))
    # if type(type(expr)) is UndefinedFunction:
    if is_function(expr):
        # print('undefined input expr:{}'.format(expr))
        return nsimplify(expr, rational=True)

    if isinstance(expr, Add):
        return Add.fromiter(
            convert_unit_to(i, target_units, unit_system) for i in expr.args)

    expr = sympify(expr)

    if not isinstance(expr, Quantity) and expr.has(Quantity):
        try:
            expr = expr.replace(
                lambda x: isinstance(x, Quantity),
                lambda x: x.convert_to(target_units, unit_system))
        except OSError:
            raise OSError('problem converting {} to {}\n{}'.format(
                expr, target_units, unit_system))

    def get_total_scale_factor(expr):
        if isinstance(expr, Mul):
            return reduce(lambda x, y: x * y,
                          [get_total_scale_factor(i) for i in expr.args])
        elif isinstance(expr, Pow):
            return get_total_scale_factor(expr.base)**expr.exp
        elif isinstance(expr, Quantity):
            return unit_system.get_quantity_scale_factor(expr)
        return expr

    if expr == target_units:
        return expr

    depmat = _get_conversion_matrix_for_expr(expr, target_units, unit_system)
    if depmat is None:
        if raise_errors:
            raise NameError('cannot convert {} to {} {}'.format(
                expr, target_units, unit_system))
        return nsimplify(expr, rational=True)

    expr_scale_factor = get_total_scale_factor(expr)
    result = expr_scale_factor * Mul.fromiter(
        (1 / get_total_scale_factor(u) * u)**p
        for u, p in zip(target_units, depmat))
    return nsimplify(result, rational=True)