Exemplo n.º 1
0
    def expand(self, **hints):
        expr = self.args[0]
        condition = self._condition

        if not is_random(expr):
            return expr

        if isinstance(expr, Add):
            return Add.fromiter(
                Expectation(a, condition=condition).expand()
                for a in expr.args)

        expand_expr = _expand(expr)
        if isinstance(expand_expr, Add):
            return Add.fromiter(
                Expectation(a, condition=condition).expand()
                for a in expand_expr.args)

        elif isinstance(expr, Mul):
            rv = []
            nonrv = []
            for a in expr.args:
                if is_random(a):
                    rv.append(a)
                else:
                    nonrv.append(a)
            return Mul.fromiter(nonrv) * Expectation(Mul.fromiter(rv),
                                                     condition=condition)

        return self
Exemplo n.º 2
0
def cancel_terms(sym, x_term, coef):
    if coef.is_Add:
        for arg_c in coef.args:
            sym = cancel_terms(sym, x_term, arg_c)
    else:
        terms = Add.make_args(sym)
        return Add.fromiter(t for t in terms if t != x_term*coef)
Exemplo n.º 3
0
    def expand(self, **hints):
        arg1 = self.args[0]
        arg2 = self.args[1]
        condition = self._condition

        if arg1 == arg2:
            return Variance(arg1, condition).expand()

        if not is_random(arg1):
            return S.Zero
        if not is_random(arg2):
            return S.Zero

        arg1, arg2 = sorted([arg1, arg2], key=default_sort_key)

        if isinstance(arg1, RandomSymbol) and isinstance(arg2, RandomSymbol):
            return Covariance(arg1, arg2, condition)

        coeff_rv_list1 = self._expand_single_argument(arg1.expand())
        coeff_rv_list2 = self._expand_single_argument(arg2.expand())

        addends = [
            a * b * Covariance(*sorted([r1, r2], key=default_sort_key),
                               condition=condition)
            for (a, r1) in coeff_rv_list1 for (b, r2) in coeff_rv_list2
        ]
        return Add.fromiter(addends)
Exemplo n.º 4
0
 def _eval_derivative(self, x):
     from sympy import Add
     terms = []
     args = list(self.args)
     for i in range(len(args)):
         factors = args[:i] + [args[i].diff(x)] + args[i+1:]
         terms.append(hadamard_product(*factors))
     return Add.fromiter(terms)
Exemplo n.º 5
0
 def _print_Add(self, expr):
     if len(expr.args) != 2:
         return "add({}, {})".format(
             self._print(expr.args[0]),
             self._print(Add.fromiter(expr.args[1:])))
     return "add({}, {})".format(
         self._print(expr.args[0]),
         self._print(expr.args[1]),
     )
Exemplo n.º 6
0
 def _print_Add(self, expr):
     if len(expr.args) != 2:
         return "add({}, {})".format(
             self._print(expr.args[0]),
             self._print(Add.fromiter(expr.args[1:]))
         )
     return "add({}, {})".format(
         self._print(expr.args[0]),
         self._print(expr.args[1]),
     )
Exemplo n.º 7
0
    def expand(self, **hints):
        expr = self.args[0]
        condition = self._condition
        if not is_random(expr):
            return expr

        if isinstance(expr, Add):
            return Add.fromiter(
                Expectation(a, condition=condition).expand()
                for a in expr.args)

        expand_expr = _expand(expr)
        if isinstance(expand_expr, Add):
            return Add.fromiter(
                Expectation(a, condition=condition).expand()
                for a in expand_expr.args)

        elif isinstance(expr, (Mul, MatMul)):
            rv = []
            nonrv = []
            postnon = []

            for a in expr.args:
                if is_random(a):
                    if rv:
                        rv.extend(postnon)
                    else:
                        nonrv.extend(postnon)
                    postnon = []
                    rv.append(a)
                elif a.is_Matrix:
                    postnon.append(a)
                else:
                    nonrv.append(a)

            # In order to avoid infinite-looping (MatMul may call .doit() again),
            # do not rebuild
            if len(nonrv) == 0:
                return self
            return Mul.fromiter(nonrv) * Expectation(
                Mul.fromiter(rv), condition=condition) * Mul.fromiter(postnon)

        return self
Exemplo n.º 8
0
def dot(vect1, vect2):
    """
    Returns dot product of two vectors.

    Examples
    ========

    >>> from sympy.vector import CoordSys3D
    >>> from sympy.vector.vector import dot
    >>> R = CoordSys3D('R')
    >>> v1 = R.i + R.j + R.k
    >>> v2 = R.x * R.i + R.y * R.j + R.z * R.k
    >>> dot(v1, v2)
    R.x + R.y + R.z

    """
    if isinstance(vect1, Add):
        return Add.fromiter(dot(i, vect2) for i in vect1.args)
    if isinstance(vect2, Add):
        return Add.fromiter(dot(vect1, i) for i in vect2.args)
    if isinstance(vect1, BaseVector) and isinstance(vect2, BaseVector):
        if vect1._sys == vect2._sys:
            return S.One if vect1 == vect2 else S.Zero
        from .functions import express

        try:
            v = express(vect2, vect1._sys)
        except ValueError:
            return Dot(vect1, vect2)
        else:
            return dot(vect1, v)
    if isinstance(vect1, VectorZero) or isinstance(vect2, VectorZero):
        return S.Zero
    if isinstance(vect1, VectorMul):
        v1, m1 = next(iter(vect1.components.items()))
        return m1 * dot(v1, vect2)
    if isinstance(vect2, VectorMul):
        v2, m2 = next(iter(vect2.components.items()))
        return m2 * dot(vect1, v2)

    return Dot(vect1, vect2)
Exemplo n.º 9
0
def dot(vect1, vect2):
    """
    Returns dot product of two vectors.

    Examples
    ========

    >>> from sympy.vector import CoordSys3D
    >>> from sympy.vector.vector import dot
    >>> R = CoordSys3D('R')
    >>> v1 = R.i + R.j + R.k
    >>> v2 = R.x * R.i + R.y * R.j + R.z * R.k
    >>> dot(v1, v2)
    R.x + R.y + R.z

    """
    if isinstance(vect1, Add):
        return Add.fromiter(dot(i, vect2) for i in vect1.args)
    if isinstance(vect2, Add):
        return Add.fromiter(dot(vect1, i) for i in vect2.args)
    if isinstance(vect1, BaseVector) and isinstance(vect2, BaseVector):
        if vect1._sys == vect2._sys:
            return S.One if vect1 == vect2 else S.Zero
        try:
            from .functions import express
            return dot(vect1, express(vect2, vect1._sys))
        except:
            return Dot(vect1, vect2)
    if isinstance(vect1, VectorZero) or isinstance(vect2, VectorZero):
        return S.Zero
    if isinstance(vect1, VectorMul):
        v1, m1 = next(iter(vect1.components.items()))
        return m1*dot(v1, vect2)
    if isinstance(vect2, VectorMul):
        v2, m2 = next(iter(vect2.components.items()))
        return m2*dot(vect1, v2)

    return Dot(vect1, vect2)
    def expand(self, **hints):
        arg1 = self.args[0]
        arg2 = self.args[1]
        condition = self._condition

        if arg1 == arg2:
            return VarianceMatrix(arg1, condition).expand()

        if not is_random(arg1) or not is_random(arg2):
            return ZeroMatrix(*self.shape)

        if isinstance(arg1, RandomSymbol) and isinstance(arg2, RandomSymbol):
            return CrossCovarianceMatrix(arg1, arg2, condition)

        coeff_rv_list1 = self._expand_single_argument(arg1.expand())
        coeff_rv_list2 = self._expand_single_argument(arg2.expand())

        addends = [a*CrossCovarianceMatrix(r1, r2, condition=condition)*b.transpose()
                   for (a, r1) in coeff_rv_list1 for (b, r2) in coeff_rv_list2]
        return Add.fromiter(addends)
Exemplo n.º 11
0
def convert_to(expr, target_units):
    """
    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 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.66053904e-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.62950196312651e-20*gravitational_constant**(-0.5)*hbar**0.5*speed_of_light**0.5

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

    if isinstance(expr, Add):
        return Add.fromiter(convert_to(i, target_units) 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))

    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 expr.scale_factor
        return expr

    depmat = _get_conversion_matrix_for_expr(expr, target_units)
    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.º 12
0
 def recurse_expr(expr, index_ranges={}):
     if expr.is_Mul:
         nonmatargs = []
         pos_arg = []
         pos_ind = []
         dlinks = {}
         link_ind = []
         counter = 0
         args_ind = []
         for arg in expr.args:
             retvals = recurse_expr(arg, index_ranges)
             assert isinstance(retvals, list)
             if isinstance(retvals, list):
                 for i in retvals:
                     args_ind.append(i)
             else:
                 args_ind.append(retvals)
         for arg_symbol, arg_indices in args_ind:
             if arg_indices is None:
                 nonmatargs.append(arg_symbol)
                 continue
             if isinstance(arg_symbol, MatrixElement):
                 arg_symbol = arg_symbol.args[0]
             pos_arg.append(arg_symbol)
             pos_ind.append(arg_indices)
             link_ind.append([None] * len(arg_indices))
             for i, ind in enumerate(arg_indices):
                 if ind in dlinks:
                     other_i = dlinks[ind]
                     link_ind[counter][i] = other_i
                     link_ind[other_i[0]][other_i[1]] = (counter, i)
                 dlinks[ind] = (counter, i)
             counter += 1
         counter2 = 0
         lines = {}
         while counter2 < len(link_ind):
             for i, e in enumerate(link_ind):
                 if None in e:
                     line_start_index = (i, e.index(None))
                     break
             cur_ind_pos = line_start_index
             cur_line = []
             index1 = pos_ind[cur_ind_pos[0]][cur_ind_pos[1]]
             while True:
                 d, r = cur_ind_pos
                 if pos_arg[d] != 1:
                     if r % 2 == 1:
                         cur_line.append(transpose(pos_arg[d]))
                     else:
                         cur_line.append(pos_arg[d])
                 next_ind_pos = link_ind[d][1 - r]
                 counter2 += 1
                 # Mark as visited, there will be no `None` anymore:
                 link_ind[d] = (-1, -1)
                 if next_ind_pos is None:
                     index2 = pos_ind[d][1 - r]
                     lines[(index1, index2)] = cur_line
                     break
                 cur_ind_pos = next_ind_pos
         ret_indices = list(j for i in lines for j in i)
         lines = {
             k: MatMul.fromiter(v) if len(v) != 1 else v[0]
             for k, v in lines.items()
         }
         return [(Mul.fromiter(nonmatargs), None)] + [(MatrixElement(
             a, i, j), (i, j)) for (i, j), a in lines.items()]
     elif expr.is_Add:
         res = [recurse_expr(i) for i in expr.args]
         d = collections.defaultdict(list)
         for res_addend in res:
             scalar = 1
             for elem, indices in res_addend:
                 if indices is None:
                     scalar = elem
                     continue
                 indices = tuple(sorted(indices, key=default_sort_key))
                 d[indices].append(scalar *
                                   remove_matelement(elem, *indices))
                 scalar = 1
         return [(MatrixElement(Add.fromiter(v), *k), k)
                 for k, v in d.items()]
     elif isinstance(expr, KroneckerDelta):
         i1, i2 = expr.args
         return [(MatrixElement(S.One, i1, i2), (i1, i2))]
     elif isinstance(expr, MatrixElement):
         matrix_symbol, i1, i2 = expr.args
         if i1 in index_ranges:
             r1, r2 = index_ranges[i1]
             if r1 != 0 or matrix_symbol.shape[0] != r2 + 1:
                 raise ValueError(
                     "index range mismatch: {0} vs. (0, {1})".format(
                         (r1, r2), matrix_symbol.shape[0]))
         if i2 in index_ranges:
             r1, r2 = index_ranges[i2]
             if r1 != 0 or matrix_symbol.shape[1] != r2 + 1:
                 raise ValueError(
                     "index range mismatch: {0} vs. (0, {1})".format(
                         (r1, r2), matrix_symbol.shape[1]))
         if (i1 == i2) and (i1 in index_ranges):
             return [(trace(matrix_symbol), None)]
         return [(MatrixElement(matrix_symbol, i1, i2), (i1, i2))]
     elif isinstance(expr, Sum):
         return recurse_expr(
             expr.args[0],
             index_ranges={i[0]: i[1:]
                           for i in expr.args[1:]})
     else:
         return [(expr, None)]
Exemplo n.º 13
0
def get_max_coef(sym, x_term):
    return Add.fromiter(
        get_max_coef_mul(s, x_term) for s in Add.make_args(sym)
    )
Exemplo n.º 14
0
def divergence(vect, coord_sys=None, doit=True):
    """
    Returns the divergence of a vector field computed wrt the base
    scalars of the given coordinate system.

    Parameters
    ==========

    vector : Vector
        The vector operand

    coord_sys : CoordSys3D
        The coordinate system to calculate the gradient in
        Deprecated since version 1.1

    doit : bool
        If True, the result is returned after calling .doit() on
        each component. Else, the returned expression contains
        Derivative instances

    Examples
    ========

    >>> from sympy.vector import CoordSys3D, divergence
    >>> R = CoordSys3D('R')
    >>> v1 = R.x*R.y*R.z * (R.i+R.j+R.k)

    >>> divergence(v1)
    R.x*R.y + R.x*R.z + R.y*R.z
    >>> v2 = 2*R.y*R.z*R.j
    >>> divergence(v2)
    2*R.z

    """
    coord_sys = _get_coord_sys_from_expr(vect, coord_sys)
    if len(coord_sys) == 0:
        return S.Zero
    elif len(coord_sys) == 1:
        if isinstance(vect, (Cross, Curl, Gradient)):
            return Divergence(vect)
        # TODO: is case of many coord systems, this gets a random one:
        coord_sys = next(iter(coord_sys))
        i, j, k = coord_sys.base_vectors()
        x, y, z = coord_sys.base_scalars()
        h1, h2, h3 = coord_sys.lame_coefficients()
        vx = _diff_conditional(vect.dot(i), x, h2, h3) \
             / (h1 * h2 * h3)
        vy = _diff_conditional(vect.dot(j), y, h3, h1) \
             / (h1 * h2 * h3)
        vz = _diff_conditional(vect.dot(k), z, h1, h2) \
             / (h1 * h2 * h3)
        res = vx + vy + vz
        if doit:
            return res.doit()
        return res
    else:
        if isinstance(vect, (Add, VectorAdd)):
            return Add.fromiter(divergence(i, doit=doit) for i in vect.args)
        elif isinstance(vect, (Mul, VectorMul)):
            vector = [i for i in vect.args if isinstance(i, (Vector, Cross, Gradient))][0]
            scalar = Mul.fromiter(i for i in vect.args if not isinstance(i, (Vector, Cross, Gradient)))
            res = Dot(vector, gradient(scalar)) + scalar*divergence(vector, doit=doit)
            if doit:
                return res.doit()
            return res
        elif isinstance(vect, (Cross, Curl, Gradient)):
            return Divergence(vect)
        else:
            raise Divergence(vect)
Exemplo n.º 15
0
 def recurse_expr(expr, index_ranges={}):
     if expr.is_Mul:
         nonmatargs = []
         pos_arg = []
         pos_ind = []
         dlinks = {}
         link_ind = []
         counter = 0
         args_ind = []
         for arg in expr.args:
             retvals = recurse_expr(arg, index_ranges)
             assert isinstance(retvals, list)
             if isinstance(retvals, list):
                 for i in retvals:
                     args_ind.append(i)
             else:
                 args_ind.append(retvals)
         for arg_symbol, arg_indices in args_ind:
             if arg_indices is None:
                 nonmatargs.append(arg_symbol)
                 continue
             if isinstance(arg_symbol, MatrixElement):
                 arg_symbol = arg_symbol.args[0]
             pos_arg.append(arg_symbol)
             pos_ind.append(arg_indices)
             link_ind.append([None]*len(arg_indices))
             for i, ind in enumerate(arg_indices):
                 if ind in dlinks:
                     other_i = dlinks[ind]
                     link_ind[counter][i] = other_i
                     link_ind[other_i[0]][other_i[1]] = (counter, i)
                 dlinks[ind] = (counter, i)
             counter += 1
         counter2 = 0
         lines = {}
         while counter2 < len(link_ind):
             for i, e in enumerate(link_ind):
                 if None in e:
                     line_start_index = (i, e.index(None))
                     break
             cur_ind_pos = line_start_index
             cur_line = []
             index1 = pos_ind[cur_ind_pos[0]][cur_ind_pos[1]]
             while True:
                 d, r = cur_ind_pos
                 if pos_arg[d] != 1:
                     if r % 2 == 1:
                         cur_line.append(transpose(pos_arg[d]))
                     else:
                         cur_line.append(pos_arg[d])
                 next_ind_pos = link_ind[d][1-r]
                 counter2 += 1
                 # Mark as visited, there will be no `None` anymore:
                 link_ind[d] = (-1, -1)
                 if next_ind_pos is None:
                     index2 = pos_ind[d][1-r]
                     lines[(index1, index2)] = cur_line
                     break
                 cur_ind_pos = next_ind_pos
         ret_indices = list(j for i in lines for j in i)
         lines = {k: MatMul.fromiter(v) if len(v) != 1 else v[0] for k, v in lines.items()}
         return [(Mul.fromiter(nonmatargs), None)] + [
             (MatrixElement(a, i, j), (i, j)) for (i, j), a in lines.items()
         ]
     elif expr.is_Add:
         res = [recurse_expr(i) for i in expr.args]
         d = collections.defaultdict(list)
         for res_addend in res:
             scalar = 1
             for elem, indices in res_addend:
                 if indices is None:
                     scalar = elem
                     continue
                 indices = tuple(sorted(indices, key=default_sort_key))
                 d[indices].append(scalar*remove_matelement(elem, *indices))
                 scalar = 1
         return [(MatrixElement(Add.fromiter(v), *k), k) for k, v in d.items()]
     elif isinstance(expr, KroneckerDelta):
         i1, i2 = expr.args
         if dimensions is not None:
             identity = Identity(dimensions[0])
         else:
             identity = S.One
         return [(MatrixElement(identity, i1, i2), (i1, i2))]
     elif isinstance(expr, MatrixElement):
         matrix_symbol, i1, i2 = expr.args
         if i1 in index_ranges:
             r1, r2 = index_ranges[i1]
             if r1 != 0 or matrix_symbol.shape[0] != r2+1:
                 raise ValueError("index range mismatch: {0} vs. (0, {1})".format(
                     (r1, r2), matrix_symbol.shape[0]))
         if i2 in index_ranges:
             r1, r2 = index_ranges[i2]
             if r1 != 0 or matrix_symbol.shape[1] != r2+1:
                 raise ValueError("index range mismatch: {0} vs. (0, {1})".format(
                     (r1, r2), matrix_symbol.shape[1]))
         if (i1 == i2) and (i1 in index_ranges):
             return [(trace(matrix_symbol), None)]
         return [(MatrixElement(matrix_symbol, i1, i2), (i1, i2))]
     elif isinstance(expr, Sum):
         return recurse_expr(
             expr.args[0],
             index_ranges={i[0]: i[1:] for i in expr.args[1:]}
         )
     else:
         return [(expr, None)]
Exemplo n.º 16
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.º 17
0
 def as_explicit(self):
     return Add.fromiter([arg.as_explicit() for arg in self.args])
Exemplo n.º 18
0
 def do_convert(self, expr, indices):
     if isinstance(expr, ArrayTensorProduct):
         cumul = list(accumulate([0] + [get_rank(arg) for arg in expr.args]))
         indices_grp = [indices[cumul[i]:cumul[i+1]] for i in range(len(expr.args))]
         return Mul.fromiter(self.do_convert(arg, ind) for arg, ind in zip(expr.args, indices_grp))
     if isinstance(expr, ArrayContraction):
         new_indices = [None for i in range(get_rank(expr.expr))]
         limits = []
         bottom_shape = get_shape(expr.expr)
         for contraction_index_grp in expr.contraction_indices:
             d = Dummy(f"d{self.count_dummies}")
             self.count_dummies += 1
             dim = bottom_shape[contraction_index_grp[0]]
             limits.append((d, 0, dim-1))
             for i in contraction_index_grp:
                 new_indices[i] = d
         j = 0
         for i in range(len(new_indices)):
             if new_indices[i] is None:
                 new_indices[i] = indices[j]
                 j += 1
         newexpr = self.do_convert(expr.expr, new_indices)
         return Sum(newexpr, *limits)
     if isinstance(expr, ArrayDiagonal):
         new_indices = [None for i in range(get_rank(expr.expr))]
         ind_pos = expr._push_indices_down(expr.diagonal_indices, list(range(len(indices))), get_rank(expr))
         for i, index in zip(ind_pos, indices):
             if isinstance(i, collections.abc.Iterable):
                 for j in i:
                     new_indices[j] = index
             else:
                 new_indices[i] = index
         newexpr = self.do_convert(expr.expr, new_indices)
         return newexpr
     if isinstance(expr, PermuteDims):
         permuted_indices = _apply_permutation_to_list(expr.permutation, indices)
         return self.do_convert(expr.expr, permuted_indices)
     if isinstance(expr, ArrayAdd):
         return Add.fromiter(self.do_convert(arg, indices) for arg in expr.args)
     if isinstance(expr, _ArrayExpr):
         return expr.__getitem__(tuple(indices))
     if isinstance(expr, ArrayElementwiseApplyFunc):
         return expr.function(self.do_convert(expr.expr, indices))
     if isinstance(expr, Reshape):
         shape_up = expr.shape
         shape_down = get_shape(expr.expr)
         cumul = list(accumulate([1] + list(reversed(shape_up)), operator.mul))
         one_index = Add.fromiter(i*s for i, s in zip(reversed(indices), cumul))
         dest_indices = [None for _ in shape_down]
         c = 1
         for i, e in enumerate(reversed(shape_down)):
             if c == 1:
                 if i == len(shape_down) - 1:
                     dest_indices[i] = one_index
                 else:
                     dest_indices[i] = one_index % e
             elif i == len(shape_down) - 1:
                 dest_indices[i] = one_index // c
             else:
                 dest_indices[i] = one_index // c % e
             c *= e
         dest_indices.reverse()
         return self.do_convert(expr.expr, dest_indices)
     return _get_array_element_or_slice(expr, indices)
Exemplo n.º 19
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)
Exemplo n.º 20
0
def divergence(vect, coord_sys=None, doit=True):
    """
    Returns the divergence of a vector field computed wrt the base
    scalars of the given coordinate system.

    Parameters
    ==========

    vector : Vector
        The vector operand

    coord_sys : CoordSys3D
        The coordinate system to calculate the gradient in
        Deprecated since version 1.1

    doit : bool
        If True, the result is returned after calling .doit() on
        each component. Else, the returned expression contains
        Derivative instances

    Examples
    ========

    >>> from sympy.vector import CoordSys3D, divergence
    >>> R = CoordSys3D('R')
    >>> v1 = R.x*R.y*R.z * (R.i+R.j+R.k)

    >>> divergence(v1)
    R.x*R.y + R.x*R.z + R.y*R.z
    >>> v2 = 2*R.y*R.z*R.j
    >>> divergence(v2)
    2*R.z

    """
    coord_sys = _get_coord_sys_from_expr(vect, coord_sys)
    if len(coord_sys) == 0:
        return S.Zero
    elif len(coord_sys) == 1:
        if isinstance(vect, (Cross, Curl, Gradient)):
            return Divergence(vect)
        # TODO: is case of many coord systems, this gets a random one:
        coord_sys = next(iter(coord_sys))
        i, j, k = coord_sys.base_vectors()
        x, y, z = coord_sys.base_scalars()
        h1, h2, h3 = coord_sys.lame_coefficients()
        vx = _diff_conditional(vect.dot(i), x, h2, h3) \
             / (h1 * h2 * h3)
        vy = _diff_conditional(vect.dot(j), y, h3, h1) \
             / (h1 * h2 * h3)
        vz = _diff_conditional(vect.dot(k), z, h1, h2) \
             / (h1 * h2 * h3)
        res = vx + vy + vz
        if doit:
            return res.doit()
        return res
    else:
        if isinstance(vect, (Add, VectorAdd)):
            return Add.fromiter(divergence(i, doit=doit) for i in vect.args)
        elif isinstance(vect, (Mul, VectorMul)):
            vector = [
                i for i in vect.args
                if isinstance(i, (Vector, Cross, Gradient))
            ][0]
            scalar = Mul.fromiter(
                i for i in vect.args
                if not isinstance(i, (Vector, Cross, Gradient)))
            res = Dot(
                vector,
                gradient(scalar)) + scalar * divergence(vector, doit=doit)
            if doit:
                return res.doit()
            return res
        elif isinstance(vect, (Cross, Curl, Gradient)):
            return Divergence(vect)
        else:
            raise Divergence(vect)
Exemplo n.º 21
0
def unify(expr, unit_registry, to_symbol=None, verbose=False):
    """adds unit conversion factors to composed functions"""
    if verbose:
        print('unify: to_symbol:', to_symbol)
    if hasattr(expr, 'rhs'):
        return Eq(
            expr.lhs,
            unify(expr.rhs, unit_registry, to_symbol=expr.lhs,
                  verbose=verbose))
    if isinstance(expr, Add):
        if verbose:
            print('unify: Adding expression: {} -> {}'.format(
                expr, get_expr_unit(to_symbol, unit_registry, verbose)))
        return Add.fromiter([
            unify(arg, unit_registry, to_symbol, verbose) for arg in expr.args
        ])

    expr_unit = get_expr_unit(expr, unit_registry, verbose)

    if verbose:
        print('unify: {} unit {}'.format(expr, expr_unit))
        print('unify: {} symbols {}'.format(expr, expr.free_symbols))
        print('unify: {} symbols {}'.format(to_symbol, to_symbol.free_symbols))
    try:
        assert expr.free_symbols.issubset(to_symbol.free_symbols)
    except:
        raise NameError("{} arguments not in {}".format(
            expr.free_symbols, to_symbol.free_symbols))

    if is_function(expr):
        if verbose:
            print('unify: function expression: {}'.format(expr))
        if to_symbol is not None:
            if verbose:
                print('\nunify: to_symbol args: {}'.format(to_symbol.args))
                print('unify: to_symbol free symbols: {}'.format(
                    to_symbol.free_symbols))
                print('unify: expr args: {}'.format(expr.args))
                print('unify: expr free symbols: {}'.format(expr.free_symbols))

            for k, v in unit_registry.items():
                if isinstance(expr, type(k)):
                    if len(k.free_symbols) > 0:
                        if verbose:
                            print('unify: found matching {} -> {}'.format(
                                expr, k))
                        arg_units = get_arg_units(k, unit_registry)
                        if verbose:
                            print('unify: func units:', arg_units)
                            print('unify: {}->{}'.format(expr.args, k.args))
                        expr_units = {}
                        for arg, sym in zip(expr.args, k.args):
                            to_unit = arg_units.get(sym)
                            from_unit = get_expr_unit(arg, unit_registry)
                            if (from_unit is not None) and (to_unit
                                                            is not None):
                                expr_units[arg] = convert_unit_to(
                                    arg * from_unit, to_unit,
                                    kamodo_unit_system) / to_unit
                        expr = expr.subs(expr_units)

                        if verbose:
                            print('unify: replaced args', expr)

    expr = unify_args(expr, unit_registry, to_symbol, verbose)

    if (to_symbol is not None) & (expr_unit is not None):
        to_unit = get_expr_unit(to_symbol, unit_registry, verbose)
        if verbose:
            print('unify: to_unit {}'.format(to_unit))
        expr_dimensions = get_dimensions(expr_unit)
        to_dimensions = get_dimensions(to_unit)
        if expr_dimensions.compare(to_dimensions) == 0:
            if verbose:
                print('unify: {} [{}] -> to_symbol: {}[{}]'.format(
                    expr, expr_unit, to_symbol, to_unit))
            expr = convert_unit_to(expr * expr_unit, to_unit,
                                   kamodo_unit_system) / to_unit
        else:
            if verbose:
                print('unify: registry:')
                for k, v in unit_registry.items():
                    print('unify:\t{} -> {}'.format(k, v))
                print('compare:{}'.format(
                    expr_dimensions.compare(to_dimensions)))
                error_msg = 'cannot convert {} [{}] {} to {}[{}] {}'.format(
                    expr, expr_unit, expr_dimensions, to_symbol, to_unit,
                    to_dimensions)
                print(error_msg)
            raise NameError(error_msg)

    return expr