o
    ohQ                    @  sr  d dl mZ d dlmZ d dlmZ d dlmZ d dlm	Z	 d dl
mZmZmZmZmZmZmZmZmZmZmZ d dlmZ d dlmZmZ d d	lmZ d d
lmZ d dlmZ d dl m!Z" d dl#m$Z$ d dl%m&Z&m'Z'm(Z( d dl)m*Z* G dd deZ+G dd deZ,G dd deZ-G dd deZ.G dd deZ/G dd deZ0G dd deZ1dd Z2G d d! d!eZ3G d"d# d#eZ4G d$d% d%eZ5G d&d' d'e5Z6G d(d) d)eZ7G d*d+ d+eZ8G d,d- d-eZ9dNd1d2Z:dOd3d4Z;d5d6 Z<dPd7d8Z=dPd9d:Z>d;d< Z?d=d> Z@d?d@ ZAdAdB ZBdCdD ZCdEdF ZDG dGdH dHZEG dIdJ dJeEeFZGG dKdL dLeEeHZId dMlJmKZK d/S )Q    )annotations)Anyreduce)permutations)Permutation)BasicExprFunctiondiffPowMulAddLambdaSTupleDict)cacheit)SymbolDummy)Str)_sympify	factorial)ImmutableDenseMatrix)solve)sympy_deprecation_warningSymPyDeprecationWarningignore_warnings)ImmutableDenseNDimArrayc                      s8   e Zd ZdZ fddZedd Zedd Z  ZS )Manifolda  
    A mathematical manifold.

    Explanation
    ===========

    A manifold is a topological space that locally resembles
    Euclidean space near each point [1].
    This class does not provide any means to study the topological
    characteristics of the manifold that it represents, though.

    Parameters
    ==========

    name : str
        The name of the manifold.

    dim : int
        The dimension of the manifold.

    Examples
    ========

    >>> from sympy.diffgeom import Manifold
    >>> m = Manifold('M', 2)
    >>> m
    M
    >>> m.dim
    2

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Manifold
    c                   s:   t |ts	t|}t|}t | ||}tdg |_|S )Nz
            Manifold.patches is deprecated. The Manifold object is now
            immutable. Instead use a separate list to keep track of the
            patches.
            )
isinstancer   r   super__new___deprecated_listpatches)clsnamedimkwargsobj	__class__ k/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/sympy/diffgeom/diffgeom.pyr#   F   s   
zManifold.__new__c                 C  
   | j d S Nr   argsselfr-   r-   r.   r'   T      
zManifold.namec                 C  r/   N   r1   r3   r-   r-   r.   r(   X   r5   zManifold.dim)	__name__
__module____qualname____doc__r#   propertyr'   r(   __classcell__r-   r-   r+   r.   r    !   s    $
r    c                      sD   e Zd ZdZ fddZedd Zedd Zedd	 Z  Z	S )
Patcha  
    A patch on a manifold.

    Explanation
    ===========

    Coordinate patch, or patch in short, is a simply-connected open set around
    a point in the manifold [1]. On a manifold one can have many patches that
    do not always include the whole manifold. On these patches coordinate
    charts can be defined that permit the parameterization of any point on the
    patch in terms of a tuple of real numbers (the coordinates).

    This class does not provide any means to study the topological
    characteristics of the patch that it represents.

    Parameters
    ==========

    name : str
        The name of the patch.

    manifold : Manifold
        The manifold on which the patch is defined.

    Examples
    ========

    >>> from sympy.diffgeom import Manifold, Patch
    >>> m = Manifold('M', 2)
    >>> p = Patch('P', m)
    >>> p
    P
    >>> p.dim
    2

    References
    ==========

    .. [1] G. Sussman, J. Wisdom, W. Farr, Functional Differential Geometry
           (2013)

    c                   s@   t |ts	t|}t | ||}|jj| tdg |_|S )Nz
            Patch.coord_systms is deprecated. The Patch class is now
            immutable. Instead use a separate list to keep track of coordinate
            systems.
            )	r!   r   r"   r#   manifoldr%   appendr$   coord_systems)r&   r'   r?   r)   r*   r+   r-   r.   r#      s   
zPatch.__new__c                 C  r/   r0   r1   r3   r-   r-   r.   r'      r5   z
Patch.namec                 C  r/   r6   r1   r3   r-   r-   r.   r?      r5   zPatch.manifoldc                 C     | j jS Nr?   r(   r3   r-   r-   r.   r(         z	Patch.dim)
r8   r9   r:   r;   r#   r<   r'   r?   r(   r=   r-   r-   r+   r.   r>   ]   s    *

r>   c                      s>  e Zd ZdZdi f fdd	Zedd Zedd Zed	d
 Zedd Z	edd Z
edd Zdd Zedd Zedd Zeedd Zedd Zd;ddZedd  Zed!d" Zd<d#d$Zd%d& Zd<d'd(ZeZd<d)d*Zd+d, Zd-d. Zd/d0 ZeZd1d2 Z e Z!d3d4 Z"d5d6 Z#d7d8 Z$d9d: Z%  Z&S )=CoordSystemai  
    A coordinate system defined on the patch.

    Explanation
    ===========

    Coordinate system is a system that uses one or more coordinates to uniquely
    determine the position of the points or other geometric elements on a
    manifold [1].

    By passing ``Symbols`` to *symbols* parameter, user can define the name and
    assumptions of coordinate symbols of the coordinate system. If not passed,
    these symbols are generated automatically and are assumed to be real valued.

    By passing *relations* parameter, user can define the transform relations of
    coordinate systems. Inverse transformation and indirect transformation can
    be found automatically. If this parameter is not passed, coordinate
    transformation cannot be done.

    Parameters
    ==========

    name : str
        The name of the coordinate system.

    patch : Patch
        The patch where the coordinate system is defined.

    symbols : list of Symbols, optional
        Defines the names and assumptions of coordinate symbols.

    relations : dict, optional
        Key is a tuple of two strings, who are the names of the systems where
        the coordinates transform from and transform to.
        Value is a tuple of the symbols before transformation and a tuple of
        the expressions after transformation.

    Examples
    ========

    We define two-dimensional Cartesian coordinate system and polar coordinate
    system.

    >>> from sympy import symbols, pi, sqrt, atan2, cos, sin
    >>> from sympy.diffgeom import Manifold, Patch, CoordSystem
    >>> m = Manifold('M', 2)
    >>> p = Patch('P', m)
    >>> x, y = symbols('x y', real=True)
    >>> r, theta = symbols('r theta', nonnegative=True)
    >>> relation_dict = {
    ... ('Car2D', 'Pol'): [(x, y), (sqrt(x**2 + y**2), atan2(y, x))],
    ... ('Pol', 'Car2D'): [(r, theta), (r*cos(theta), r*sin(theta))]
    ... }
    >>> Car2D = CoordSystem('Car2D', p, (x, y), relation_dict)
    >>> Pol = CoordSystem('Pol', p, (r, theta), relation_dict)

    ``symbols`` property returns ``CoordinateSymbol`` instances. These symbols
    are not same with the symbols used to construct the coordinate system.

    >>> Car2D
    Car2D
    >>> Car2D.dim
    2
    >>> Car2D.symbols
    (x, y)
    >>> _[0].func
    <class 'sympy.diffgeom.diffgeom.CoordinateSymbol'>

    ``transformation()`` method returns the transformation function from
    one coordinate system to another. ``transform()`` method returns the
    transformed coordinates.

    >>> Car2D.transformation(Pol)
    Lambda((x, y), Matrix([
    [sqrt(x**2 + y**2)],
    [      atan2(y, x)]]))
    >>> Car2D.transform(Pol)
    Matrix([
    [sqrt(x**2 + y**2)],
    [      atan2(y, x)]])
    >>> Car2D.transform(Pol, [1, 2])
    Matrix([
    [sqrt(5)],
    [atan(2)]])

    ``jacobian()`` method returns the Jacobian matrix of coordinate
    transformation between two systems. ``jacobian_determinant()`` method
    returns the Jacobian determinant of coordinate transformation between two
    systems.

    >>> Pol.jacobian(Car2D)
    Matrix([
    [cos(theta), -r*sin(theta)],
    [sin(theta),  r*cos(theta)]])
    >>> Pol.jacobian(Car2D, [1, pi/2])
    Matrix([
    [0, -1],
    [1,  0]])
    >>> Car2D.jacobian_determinant(Pol)
    1/sqrt(x**2 + y**2)
    >>> Car2D.jacobian_determinant(Pol, [1,0])
    1

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Coordinate_system

    Nc                   s  t  ts	t  |d u rF|dd }|d u r&t fddt|jD  }n[td| dddd |D  dd	d
d tdd |D  }n;g }|D ]2}t |tr`|	t|j
fi |jj qJt |tr|td| d|dd	d
d |	t|dd qJt| }i }	| D ]?\}
}|
\}}t |tst|}t |tst|}t||}t |trt|jt|jf}nt|d t|d f}||	|< qt|	}t |  |||}tdi |_dd |D |_|jj	| dd |D |_t |_|S )Nnamesc                   s"   g | ]}t d  j|f ddqS )z%s_%sTreal)r   r'   .0ir'   r-   r.   
<listcomp>  s    z'CoordSystem.__new__.<locals>.<listcomp>zx
The 'names' argument to CoordSystem is deprecated. Use 'symbols' instead. That
is, replace

    CoordSystem(..., names=z')

with

    CoordSystem(..., symbols=[z, c                 S  s   g | ]
}d t | d qS )zSymbol(z, real=True))reprrK   nr-   r-   r.   rN   '      z])
                    1.7deprecated-diffgeom-mutabledeprecated_since_versionactive_deprecations_targetc                 S  s   g | ]}t |d dqS )TrH   )r   rP   r-   r-   r.   rN   -      z

Passing a string as the coordinate symbol name to CoordSystem is deprecated.
Pass a Symbol with the appropriate name and assumptions instead.

That is, replace z with Symbol(z&, real=True).
                        TrH   r   r7   z
            CoordSystem.transforms is deprecated. The CoordSystem class is now
            immutable. Use the 'relations' keyword argument to the
            CoordSystems() constructor to specify relations.
            c                 S     g | ]}t |qS r-   )strrP   r-   r-   r.   rN   `      c                 S  s   g | ]}t t|qS r-   )r   rZ   rP   r-   r-   r.   rN   b  rX   )r!   r   getr   ranger(   r   joinr   r@   r'   _assumptions	generatorrZ   itemsr   tuple	signatureexprr   r"   r#   _deprecated_dict
transforms_namespatchrA   _dummiesr   _dummy)r&   r'   rh   symbols	relationsr)   rG   symssrel_tempkvs1s2keyr*   r+   rM   r.   r#     s|   









zCoordSystem.__new__c                 C  r/   r0   r1   r3   r-   r-   r.   r'   g  r5   zCoordSystem.namec                 C  r/   r6   r1   r3   r-   r-   r.   rh   k  r5   zCoordSystem.patchc                 C  rB   rC   )rh   r?   r3   r-   r-   r.   r?   o  rE   zCoordSystem.manifoldc                   s    t  fddt jd D S )Nc                 3  s*    | ]\}}t  |fi |jjV  qd S rC   )CoordinateSymbolr_   r`   )rK   rL   rn   r3   r-   r.   	<genexpr>u  s    z&CoordSystem.symbols.<locals>.<genexpr>   )rb   	enumerater2   r3   r-   r3   r.   rk   s  s   zCoordSystem.symbolsc                 C  r/   )N   r1   r3   r-   r-   r.   rl   x  r5   zCoordSystem.relationsc                 C  rB   rC   )rh   r(   r3   r-   r-   r.   r(   |  rE   zCoordSystem.dimc                 C  s   | j d }t| j|j}| |krt| j}n*|| jv r%t| j| d }n|ddd | jv r8t| || }nt| | |}t||S )a  
        Return coordinate transformation function from *self* to *sys*.

        Parameters
        ==========

        sys : CoordSystem

        Returns
        =======

        sympy.Lambda

        Examples
        ========

        >>> from sympy.diffgeom.rn import R2_r, R2_p
        >>> R2_r.transformation(R2_p)
        Lambda((x, y), Matrix([
        [sqrt(x**2 + y**2)],
        [      atan2(y, x)]]))

        rw   r7   N)	r2   r   r'   Matrixrk   rl   _inverse_transformation_indirect_transformationr   )r4   sysrc   rt   rd   r-   r-   r.   transformation  s   


zCoordSystem.transformationc                 C  sj   t dd t||D t| dd}t|dkr!d}t|||t|dkr1d}t||||d S )	Nc                 S     g | ]
}|d  |d  qS r   r7   r-   rK   tr-   r-   r.   rN     rR   z.CoordSystem._solve_inverse.<locals>.<listcomp>Tdictr   z,Cannot solve inverse relation from {} to {}.r7   z1Obtained multiple inverse relation from {} to {}.)r   ziplistlenNotImplementedErrorformat
ValueError)sym1sym2exprs	sys1_name	sys2_namerettempr-   r-   r.   _solve_inverse  s   zCoordSystem._solve_inversec                   s@   | |}| |j|j||j|j t|j} fdd|D S )Nc                      g | ]} | qS r-   r-   rK   rn   inv_resultsr-   r.   rN     r[   z7CoordSystem._inverse_transformation.<locals>.<listcomp>)	transformr   rk   r'   rb   )r&   sys1sys2forwardrc   r-   r   r.   r|     s   

z#CoordSystem._inverse_transformationc                   s   |j }| ||}g }t||dd  D ]@\}}||f|v r(||||f  q|||f \}}	tdd |D }
| ||
|	||tfdd|D ||
f q|jd }| |D ]\}t fdd|D  q^ S )Nr7   c                 s  s    | ]}t  V  qd S rC   )r   rJ   r-   r-   r.   rv     s    z7CoordSystem._indirect_transformation.<locals>.<genexpr>c                 3  s    | ]} | V  qd S rC   r-   r   )r   r-   r.   rv         rw   c                 3  s     | ]}| t V  qd S rC   )subsr   rK   e)r   newsymsr-   r.   rv         )rl   	_dijkstrar   r@   rb   r   r2   )r&   r   r   relpathrf   rr   rs   r   	inv_exprsr   rm   newexprsr-   )r   r   r   r.   r}     s    
z$CoordSystem._indirect_transformationc                   s,  | j }i  | D ]&\}}| vr|h |< n | | | vr(|h |< q	 | | q	dd  D  fdd}|| j 	 t dd dd	 }d } D ]\}}	d	|	d	   k rf|krrn qV|	d
 sr|	d	 }|}qV|d u rxn|| qD|j d }
|
|j |
|jgkrtd|
S )Nc                 S  s   i | ]}|d g d gqS r   r-   )rK   r~   r-   r-   r.   
<dictcomp>  rX   z)CoordSystem._dijkstra.<locals>.<dictcomp>c                   s   d|  d<  |  D ]3}|  d d }| d |ks"| d s=|| d< t |  d | d< | d |  q
d S )Nr7   rw   r   )r   r@   )r~   newsysdistancegraph	path_dictr-   r.   visit  s   z$CoordSystem._dijkstra.<locals>.visitTc                 S  s   | d S r0   r-   )xr-   r-   r.   <lambda>  s    z'CoordSystem._dijkstra.<locals>.<lambda>)rt   r   rw   r7   z)Two coordinate systems are not connected.)	rl   keysaddr'   maxvaluesra   r@   KeyError)r   r   rl   rr   rs   r   min_distancer   r~   lstresultr-   r   r.   r     s:   
	$zCoordSystem._dijkstraTFc                 C  s\   t dddd t||\}}t|t|f| j|< |r$| |||j| < |r,|   d S d S )Nz
            The CoordSystem.connect_to() method is deprecated. Instead,
            generate a new instance of CoordSystem with the 'relations'
            keyword argument (CoordSystem classes are now immutable).
            rS   rT   rU   )r   dummyfyr{   rf   _inv_transf_fill_gaps_in_transformations)r4   to_sysfrom_coordsto_exprsinversefill_in_gapsr-   r-   r.   
connect_to	  s   
zCoordSystem.connect_toc                   sV   dd | D }t dd t||D t| ddd   fdd| D  t|t fS )Nc                 S     g | ]}|  qS r-   as_dummyrJ   r-   r-   r.   rN      r[   z+CoordSystem._inv_transf.<locals>.<listcomp>c                 S  r   r   r-   r   r-   r-   r.   rN   "  rR   Tr   r   c                   r   r-   r-   )rK   fcinv_tor-   r.   rN   $  r[   )r   r   r   r{   )r   r   inv_fromr-   r   r.   r     s   zCoordSystem._inv_transfc                   C  s   t rC   )r   r-   r-   r-   r.   r   '  s   z)CoordSystem._fill_gaps_in_transformationsc                 C  s8   |du r| j }| |kr| |}|| }|S t|}|S )a  
        Return the result of coordinate transformation from *self* to *sys*.
        If coordinates are not given, coordinate symbols of *self* are used.

        Parameters
        ==========

        sys : CoordSystem

        coordinates : Any iterable, optional.

        Returns
        =======

        sympy.ImmutableDenseMatrix containing CoordinateSymbol

        Examples
        ========

        >>> from sympy.diffgeom.rn import R2_r, R2_p
        >>> R2_r.transform(R2_p)
        Matrix([
        [sqrt(x**2 + y**2)],
        [      atan2(y, x)]])
        >>> R2_r.transform(R2_p, [0, 1])
        Matrix([
        [   1],
        [pi/2]])

        N)rk   r   r{   )r4   r~   coordinatestransfr-   r-   r.   r   0  s   
zCoordSystem.transformc                 C  sp   t dddd t|}| |kr6tt | j| }W d   n1 s#w   Y  |d tt|d |}|S )z0Transform ``coords`` to coord system ``to_sys``.z
            The CoordSystem.coord_tuple_transform_to() method is deprecated.
            Use the CoordSystem.transform() method instead.
            rS   rT   rU   Nr7   r   )r   r{   r   r   rf   r   r   r   )r4   r   coordsr   r-   r-   r.   coord_tuple_transform_toX  s   	
z$CoordSystem.coord_tuple_transform_toc                 C  s4   |  || j}|dur|tt| j|}|S )a  
        Return the jacobian matrix of a transformation on given coordinates.
        If coordinates are not given, coordinate symbols of *self* are used.

        Parameters
        ==========

        sys : CoordSystem

        coordinates : Any iterable, optional.

        Returns
        =======

        sympy.ImmutableDenseMatrix

        Examples
        ========

        >>> from sympy.diffgeom.rn import R2_r, R2_p
        >>> R2_p.jacobian(R2_r)
        Matrix([
        [cos(theta), -rho*sin(theta)],
        [sin(theta),  rho*cos(theta)]])
        >>> R2_p.jacobian(R2_r, [1, 0])
        Matrix([
        [1, 0],
        [0, 1]])

        N)r   jacobianrk   r   r   r   )r4   r~   r   r   r-   r-   r.   r   j  s   zCoordSystem.jacobianc                 C  s   |  || S )a6  
        Return the jacobian determinant of a transformation on given
        coordinates. If coordinates are not given, coordinate symbols of *self*
        are used.

        Parameters
        ==========

        sys : CoordSystem

        coordinates : Any iterable, optional.

        Returns
        =======

        sympy.Expr

        Examples
        ========

        >>> from sympy.diffgeom.rn import R2_r, R2_p
        >>> R2_r.jacobian_determinant(R2_p)
        1/sqrt(x**2 + y**2)
        >>> R2_r.jacobian_determinant(R2_p, [1, 0])
        1

        )r   det)r4   r~   r   r-   r-   r.   jacobian_determinant  s   z CoordSystem.jacobian_determinantc                 C  
   t | |S )z?Create a ``Point`` with coordinates given in this coord system.)Point)r4   r   r-   r-   r.   point  r5   zCoordSystem.pointc                 C  
   | | S )z:Calculate the coordinates of a point in this coord system.)r   )r4   r   r-   r-   r.   point_to_coords  r5   zCoordSystem.point_to_coordsc                 C  r   )zQReturn ``BaseScalarField`` that takes a point and returns one of the coordinates.)BaseScalarFieldr4   coord_indexr-   r-   r.   base_scalar  r5   zCoordSystem.base_scalarc                       fddt  jD S )zrReturns a list of all coordinate functions.
        For more details see the ``base_scalar`` method of this class.c                      g | ]}  |qS r-   )r   rJ   r3   r-   r.   rN         z,CoordSystem.base_scalars.<locals>.<listcomp>r]   r(   r3   r-   r3   r.   base_scalars     zCoordSystem.base_scalarsc                 C  r   )zReturn a basis vector field.
        The basis vector field for this coordinate system. It is also an
        operator on scalar fields.)BaseVectorFieldr   r-   r-   r.   base_vector  s   
zCoordSystem.base_vectorc                   r   )zjReturns a list of all base vectors.
        For more details see the ``base_vector`` method of this class.c                   r   r-   )r   rJ   r3   r-   r.   rN     r   z,CoordSystem.base_vectors.<locals>.<listcomp>r   r3   r-   r3   r.   base_vectors  r   zCoordSystem.base_vectorsc                 C  s   t | |S )zReturn a basis 1-form field.
        The basis one-form field for this coordinate system. It is also an
        operator on vector fields.)Differentialcoord_functionr   r-   r-   r.   base_oneform  s   zCoordSystem.base_oneformc                   r   )zlReturns a list of all base oneforms.
        For more details see the ``base_oneform`` method of this class.c                   r   r-   )r   rJ   r3   r-   r.   rN     r   z-CoordSystem.base_oneforms.<locals>.<listcomp>r   r3   r-   r3   r.   base_oneforms  r   zCoordSystem.base_oneforms)TFrC   )'r8   r9   r:   r;   r#   r<   r'   rh   r?   rk   rl   r(   r   staticmethodr   classmethodr|   r   r}   r   r   r   r   r   r   r   jacobian_matrixr   r   r   r   r   r   coord_functionsr   r   r   r   r=   r-   r-   r+   r.   rF      sZ    mV





%



/
	

(
#
#rF   c                      s<   e Zd ZdZ fddZdd Zdd Z fdd	Z  ZS )
ru   a  A symbol which denotes an abstract value of i-th coordinate of
    the coordinate system with given context.

    Explanation
    ===========

    Each coordinates in coordinate system are represented by unique symbol,
    such as x, y, z in Cartesian coordinate system.

    You may not construct this class directly. Instead, use `symbols` method
    of CoordSystem.

    Parameters
    ==========

    coord_sys : CoordSystem

    index : integer

    Examples
    ========

    >>> from sympy import symbols, Lambda, Matrix, sqrt, atan2, cos, sin
    >>> from sympy.diffgeom import Manifold, Patch, CoordSystem
    >>> m = Manifold('M', 2)
    >>> p = Patch('P', m)
    >>> x, y = symbols('x y', real=True)
    >>> r, theta = symbols('r theta', nonnegative=True)
    >>> relation_dict = {
    ... ('Car2D', 'Pol'): Lambda((x, y), Matrix([sqrt(x**2 + y**2), atan2(y, x)])),
    ... ('Pol', 'Car2D'): Lambda((r, theta), Matrix([r*cos(theta), r*sin(theta)]))
    ... }
    >>> Car2D = CoordSystem('Car2D', p, [x, y], relation_dict)
    >>> Pol = CoordSystem('Pol', p, [r, theta], relation_dict)
    >>> x, y = Car2D.symbols

    ``CoordinateSymbol`` contains its coordinate symbol and index.

    >>> x.name
    'x'
    >>> x.coord_sys == Car2D
    True
    >>> x.index
    0
    >>> x.is_real
    True

    You can transform ``CoordinateSymbol`` into other coordinate system using
    ``rewrite()`` method.

    >>> x.rewrite(Pol)
    r*cos(theta)
    >>> sqrt(x**2 + y**2).rewrite(Pol).simplify()
    r

    c                   s6   |j d | j}t j| |fi |}||_||_|S Nrw   )r2   r'   r"   r#   	coord_sysindex)r&   r   r   assumptionsr'   r*   r+   r-   r.   r#     s
   zCoordinateSymbol.__new__c                 C  s   | j | jfS rC   )r   r   r3   r-   r-   r.   __getnewargs__   s   zCoordinateSymbol.__getnewargs__c                 C  s   | j | jftt| j  S rC   )r   r   rb   sortedassumptions0ra   r3   r-   r-   r.   _hashable_content#  s   z"CoordinateSymbol._hashable_contentc                   s2   t |tr|| j| j S t j||fi |S rC   )r!   rF   r   r   r   r"   _eval_rewrite)r4   ruler2   hintsr+   r-   r.   r   (  s   
zCoordinateSymbol._eval_rewrite)	r8   r9   r:   r;   r#   r   r   r   r=   r-   r-   r+   r.   ru     s    8ru   c                      sZ   e Zd ZdZ fddZedd Zedd Zedd	 ZdddZ	edd Z
  ZS )r   a  Point defined in a coordinate system.

    Explanation
    ===========

    Mathematically, point is defined in the manifold and does not have any coordinates
    by itself. Coordinate system is what imbues the coordinates to the point by coordinate
    chart. However, due to the difficulty of realizing such logic, you must supply
    a coordinate system and coordinates to define a Point here.

    The usage of this object after its definition is independent of the
    coordinate system that was used in order to define it, however due to
    limitations in the simplification routines you can arrive at complicated
    expressions if you use inappropriate coordinate systems.

    Parameters
    ==========

    coord_sys : CoordSystem

    coords : list
        The coordinates of the point.

    Examples
    ========

    >>> from sympy import pi
    >>> from sympy.diffgeom import Point
    >>> from sympy.diffgeom.rn import R2, R2_r, R2_p
    >>> rho, theta = R2_p.symbols

    >>> p = Point(R2_p, [rho, 3*pi/4])

    >>> p.manifold == R2
    True

    >>> p.coords()
    Matrix([
    [   rho],
    [3*pi/4]])
    >>> p.coords(R2_r)
    Matrix([
    [-sqrt(2)*rho/2],
    [ sqrt(2)*rho/2]])

    c                   (   t |}t | ||}||_||_|S rC   )r{   r"   r#   
_coord_sys_coords)r&   r   r   r)   r*   r+   r-   r.   r#   ^  
   zPoint.__new__c                 C  rB   rC   )r   rh   r3   r-   r-   r.   rh   e  rE   zPoint.patchc                 C  rB   rC   )r   r?   r3   r-   r-   r.   r?   i  rE   zPoint.manifoldc                 C  rB   rC   rD   r3   r-   r-   r.   r(   m  rE   z	Point.dimNc                 C  s   |du r| j S | j|| j S )z
        Coordinates of the point in given coordinate system. If coordinate system
        is not passed, it returns the coordinates in the coordinate system in which
        the poin was defined.
        N)r   r   r   )r4   r~   r-   r-   r.   r   q  s   zPoint.coordsc                 C  rB   rC   )r   free_symbolsr3   r-   r-   r.   r   |  rE   zPoint.free_symbolsrC   )r8   r9   r:   r;   r#   r<   rh   r?   r(   r   r   r=   r-   r-   r+   r.   r   .  s    /



r   c                      sx   e Zd ZU dZdZ fddZedd Zedd Zed	d
 Z	edd Z
edd Zdd Ze Zded<   ZS )r   a  Base scalar field over a manifold for a given coordinate system.

    Explanation
    ===========

    A scalar field takes a point as an argument and returns a scalar.
    A base scalar field of a coordinate system takes a point and returns one of
    the coordinates of that point in the coordinate system in question.

    To define a scalar field you need to choose the coordinate system and the
    index of the coordinate.

    The use of the scalar field after its definition is independent of the
    coordinate system in which it was defined, however due to limitations in
    the simplification routines you may arrive at more complicated
    expression if you use unappropriate coordinate systems.
    You can build complicated scalar fields by just building up SymPy
    expressions containing ``BaseScalarField`` instances.

    Parameters
    ==========

    coord_sys : CoordSystem

    index : integer

    Examples
    ========

    >>> from sympy import Function, pi
    >>> from sympy.diffgeom import BaseScalarField
    >>> from sympy.diffgeom.rn import R2_r, R2_p
    >>> rho, _ = R2_p.symbols
    >>> point = R2_p.point([rho, 0])
    >>> fx, fy = R2_r.base_scalars()
    >>> ftheta = BaseScalarField(R2_r, 1)

    >>> fx(point)
    rho
    >>> fy(point)
    0

    >>> (fx**2+fy**2).rcall(point)
    rho**2

    >>> g = Function('g')
    >>> fg = g(ftheta-pi)
    >>> fg.rcall(point)
    g(-pi)

    Tc                   r   rC   r   r"   r#   r   _indexr&   r   r   r)   r*   r+   r-   r.   r#     r   zBaseScalarField.__new__c                 C  r/   r0   r1   r3   r-   r-   r.   r     r5   zBaseScalarField.coord_sysc                 C  r/   r6   r1   r3   r-   r-   r.   r     r5   zBaseScalarField.indexc                 C  rB   rC   r   rh   r3   r-   r-   r.   rh     rE   zBaseScalarField.patchc                 C  rB   rC   r   r?   r3   r-   r-   r.   r?     rE   zBaseScalarField.manifoldc                 C  rB   rC   rD   r3   r-   r-   r.   r(     rE   zBaseScalarField.dimc                 G  s@   |d }t |dkst|ts| S || j}t|| j  S )ae  Evaluating the field at a point or doing nothing.
        If the argument is a ``Point`` instance, the field is evaluated at that
        point. The field is returned itself if the argument is any other
        object. It is so in order to have working recursive calling mechanics
        for all fields (check the ``__call__`` method of ``Expr``).
        r   r7   )r   r!   r   r   r   simplifyr   doit)r4   r2   r   r   r-   r-   r.   __call__  s
   zBaseScalarField.__call__zset[Any]r   )r8   r9   r:   r;   is_commutativer#   r<   r   r   rh   r?   r(   r  setr   __annotations__r=   r-   r-   r+   r.   r     s    
 4




r   c                      sh   e Zd ZdZdZ fddZedd Zedd Zed	d
 Z	edd Z
edd Zdd Z  ZS )r   aq  Base vector field over a manifold for a given coordinate system.

    Explanation
    ===========

    A vector field is an operator taking a scalar field and returning a
    directional derivative (which is also a scalar field).
    A base vector field is the same type of operator, however the derivation is
    specifically done with respect to a chosen coordinate.

    To define a base vector field you need to choose the coordinate system and
    the index of the coordinate.

    The use of the vector field after its definition is independent of the
    coordinate system in which it was defined, however due to limitations in the
    simplification routines you may arrive at more complicated expression if you
    use unappropriate coordinate systems.

    Parameters
    ==========
    coord_sys : CoordSystem

    index : integer

    Examples
    ========

    >>> from sympy import Function
    >>> from sympy.diffgeom.rn import R2_p, R2_r
    >>> from sympy.diffgeom import BaseVectorField
    >>> from sympy import pprint

    >>> x, y = R2_r.symbols
    >>> rho, theta = R2_p.symbols
    >>> fx, fy = R2_r.base_scalars()
    >>> point_p = R2_p.point([rho, theta])
    >>> point_r = R2_r.point([x, y])

    >>> g = Function('g')
    >>> s_field = g(fx, fy)

    >>> v = BaseVectorField(R2_r, 1)
    >>> pprint(v(s_field))
    / d           \|
    |---(g(x, xi))||
    \dxi          /|xi=y
    >>> pprint(v(s_field).rcall(point_r).doit())
    d
    --(g(x, y))
    dy
    >>> pprint(v(s_field).rcall(point_p))
    / d                        \|
    |---(g(rho*cos(theta), xi))||
    \dxi                       /|xi=rho*sin(theta)

    Fc                   r   rC   r   r   r+   r-   r.   r#   "  r   zBaseVectorField.__new__c                 C  r/   r0   r1   r3   r-   r-   r.   r   )  r5   zBaseVectorField.coord_sysc                 C  r/   r6   r1   r3   r-   r-   r.   r   -  r5   zBaseVectorField.indexc                 C  rB   rC   r   r3   r-   r-   r.   rh   1  rE   zBaseVectorField.patchc                 C  rB   rC   r   r3   r-   r-   r.   r?   5  rE   zBaseVectorField.manifoldc                 C  rB   rC   rD   r3   r-   r-   r.   r(   9  rE   zBaseVectorField.dimc                   s  t |st|rtd|du r| S t|t}| jj  fddt|D }|	tt
||}| }| jj} fdd|D }g }|D ]}| j|j|}	||	|j| jf  qH|	tt
||}|	tt
||}
|
	tt
|| j }
|
 S )zApply on a scalar field.
        The action of a vector field on a scalar field is a directional
        differentiation.
        If the argument is not a scalar field an error is raised.
        zAOnly scalar fields can be supplied as arguments to vector fields.Nc                       g | ]\}}t d |  qS z_#_%sr
   rK   rL   bd_varr-   r.   rN   N     
 z,BaseVectorField.__call__.<locals>.<listcomp>c                   s   g | ]}|  qS r-   )r   rK   fr
  r-   r.   rN   U  r   )covariant_ordercontravariant_orderr   r   atomsr   r   rj   rx   r   r   r   rk   r   r@   r   r   r   )r4   scalar_fieldr   d_funcsd_resultr   d_funcs_derivd_funcs_deriv_subr	  jacr   r-   r
  r.   r  =  s*   

zBaseVectorField.__call__)r8   r9   r:   r;   r  r#   r<   r   r   rh   r?   r(   r  r=   r-   r-   r+   r.   r     s    9




r   c                 C  s   |  tt}dd |D S )Nc                 S     h | ]}|j qS r-   r   r  r-   r-   r.   	<setcomp>e      z_find_coords.<locals>.<setcomp>)r  r   r   )rd   fieldsr-   r-   r.   _find_coordsb  s   r  c                      @   e Zd ZdZ fddZedd Zedd Zdd	 Z  Z	S )

Commutatora#  Commutator of two vector fields.

    Explanation
    ===========

    The commutator of two vector fields `v_1` and `v_2` is defined as the
    vector field `[v_1, v_2]` that evaluated on each scalar field `f` is equal
    to `v_1(v_2(f)) - v_2(v_1(f))`.

    Examples
    ========


    >>> from sympy.diffgeom.rn import R2_p, R2_r
    >>> from sympy.diffgeom import Commutator
    >>> from sympy import simplify

    >>> fx, fy = R2_r.base_scalars()
    >>> e_x, e_y = R2_r.base_vectors()
    >>> e_r = R2_p.base_vector(0)

    >>> c_xy = Commutator(e_x, e_y)
    >>> c_xr = Commutator(e_x, e_r)
    >>> c_xy
    0

    Unfortunately, the current code is not able to compute everything:

    >>> c_xr
    Commutator(e_x, e_rho)
    >>> simplify(c_xr(fy**2))
    -2*cos(theta)*y**2/(x**2 + y**2)

    c                   s.  t  st dkst stdkrtd krtjS t jdd  fD  }t|dkrtdd  fD r@tjS dd  fD \}} fdd|D }fd	d|D }d
}t	||D ] \}	}
t	||D ]\}}||	|
| | |||	 |
  7 }qmqd|S t
 |  } |_|_|S )Nr7   z0Only commutators of vector fields are supported.c                 S  rY   r-   )r  rK   rq   r-   r-   r.   rN     r[   z&Commutator.__new__.<locals>.<listcomp>c                 s  s    | ]}t |tV  qd S rC   )r!   r   r   r-   r-   r.   rv     s    z%Commutator.__new__.<locals>.<genexpr>c                 S  s   g | ]	}t |tqS r-   )r   r  r   r   r-   r-   r.   rN     s    c                      g | ]	}   |qS r-   expandcoeffrK   r	  )v1r-   r.   rN         c                   r!  r-   r"  r%  v2r-   r.   rN     r'  r   )r  r  r   r   Zeror  unionr   allr   r"   r#   _v1_v2)r&   r&  r)  r   bases_1bases_2coeffs_1coeffs_2resc1b1c2b2r*   r+   r&  r)  r.   r#     s8   
&zCommutator.__new__c                 C  r/   r0   r1   r3   r-   r-   r.   r&    r5   zCommutator.v1c                 C  r/   r6   r1   r3   r-   r-   r.   r)    r5   zCommutator.v2c                 C  s    |  | || |  | S )zcApply on a scalar field.
        If the argument is not a scalar field an error is raised.
        r8  )r4   r  r-   r-   r.   r    s    zCommutator.__call__)
r8   r9   r:   r;   r#   r<   r&  r)  r  r=   r-   r-   r+   r.   r  h  s    "

r  c                      s8   e Zd ZdZdZ fddZedd Zdd Z  Z	S )	r   a  Return the differential (exterior derivative) of a form field.

    Explanation
    ===========

    The differential of a form (i.e. the exterior derivative) has a complicated
    definition in the general case.
    The differential `df` of the 0-form `f` is defined for any vector field `v`
    as `df(v) = v(f)`.

    Examples
    ========

    >>> from sympy import Function
    >>> from sympy.diffgeom.rn import R2_r
    >>> from sympy.diffgeom import Differential
    >>> from sympy import pprint

    >>> fx, fy = R2_r.base_scalars()
    >>> e_x, e_y = R2_r.base_vectors()
    >>> g = Function('g')
    >>> s_field = g(fx, fy)
    >>> dg = Differential(s_field)

    >>> dg
    d(g(x, y))
    >>> pprint(dg(e_x))
    / d           \|
    |---(g(xi, y))||
    \dxi          /|xi=x
    >>> pprint(dg(e_y))
    / d           \|
    |---(g(x, xi))||
    \dxi          /|xi=y

    Applying the exterior derivative operator twice always results in:

    >>> Differential(dg)
    0
    Fc                   s8   t |rtdt|trtjS t | |}||_|S )Nz;A vector field was supplied as an argument to Differential.)	r  r   r!   r   r   r*  r"   r#   _form_field)r&   
form_fieldr*   r+   r-   r.   r#     s   
zDifferential.__new__c                 C  r/   r0   r1   r3   r-   r-   r.   r:    r5   zDifferential.form_fieldc           
      G  s  t dd |D rtdt|}|dkr#|d r!|d | jS | S | j}|}d}t|D ][}|| |j|d| ||d d   }|d| | 7 }t|d |D ]3}t|| || }	|	r|j|	f|d|  ||d |  ||d d   }|d||  | 7 }qUq.|S )a  Apply on a list of vector_fields.

        Explanation
        ===========

        If the number of vector fields supplied is not equal to 1 + the order of
        the form field inside the differential the result is undefined.

        For 1-forms (i.e. differentials of scalar fields) the evaluation is
        done as `df(v)=v(f)`. However if `v` is ``None`` instead of a vector
        field, the differential is returned unchanged. This is done in order to
        permit partial contractions for higher forms.

        In the general case the evaluation is done by applying the form field
        inside the differential on a list with one less elements than the number
        of elements in the original list. Lowering the number of vector fields
        is achieved through replacing each pair of fields by their
        commutator.

        If the arguments are not vectors or ``None``s an error is raised.
        c                 s  s,    | ]}t |d kst|o|duV  qdS )r7   N)r  r  rK   ar-   r-   r.   rv     s    $z(Differential.__call__.<locals>.<genexpr>zHThe arguments supplied to Differential should be vector fields or Nones.r7   r   Nrz   )anyr   r   rcallr9  r]   r  )
r4   vector_fieldsrp   r  rq   r   rL   r   jcr-   r-   r.   r    s.   ,8zDifferential.__call__)
r8   r9   r:   r;   r  r#   r<   r:  r  r=   r-   r-   r+   r.   r     s    )
r   c                      s(   e Zd ZdZ fddZdd Z  ZS )TensorProducta  Tensor product of forms.

    Explanation
    ===========

    The tensor product permits the creation of multilinear functionals (i.e.
    higher order tensors) out of lower order fields (e.g. 1-forms and vector
    fields). However, the higher tensors thus created lack the interesting
    features provided by the other type of product, the wedge product, namely
    they are not antisymmetric and hence are not form fields.

    Examples
    ========

    >>> from sympy.diffgeom.rn import R2_r
    >>> from sympy.diffgeom import TensorProduct

    >>> fx, fy = R2_r.base_scalars()
    >>> e_x, e_y = R2_r.base_vectors()
    >>> dx, dy = R2_r.base_oneforms()

    >>> TensorProduct(dx, dy)(e_x, e_y)
    1
    >>> TensorProduct(dx, dy)(e_y, e_x)
    0
    >>> TensorProduct(dx, fx*dy)(fx*e_x, e_y)
    x**2
    >>> TensorProduct(e_x, e_y)(fx**2, fy**2)
    4*x*y
    >>> TensorProduct(e_y, dx)(fy)
    dx

    You can nest tensor products.

    >>> tp1 = TensorProduct(dx, dy)
    >>> TensorProduct(tp1, dx)(e_x, e_y, e_x)
    1

    You can make partial contraction for instance when 'raising an index'.
    Putting ``None`` in the second argument of ``rcall`` means that the
    respective position in the tensor product is left as it is.

    >>> TP = TensorProduct
    >>> metric = TP(dx, dx) + 3*TP(dy, dy)
    >>> metric.rcall(e_y, None)
    3*dy

    Or automatically pad the args with ``None`` without specifying them.

    >>> metric.rcall(e_y)
    3*dy

    c                   sX   t dd |D  }dd |D }|r*t|dkr||d  S |t j| g|R   S |S )Nc                 S  s$   g | ]}t |t| d kr|qS r   r  r  rK   mr-   r-   r.   rN   [  s   $ z)TensorProduct.__new__.<locals>.<listcomp>c                 S  s    g | ]}t |t| r|qS r-   rC  rD  r-   r-   r.   rN   \       r7   r   )r   r   r"   r#   )r&   r2   scalarmultifieldsr+   r-   r.   r#   Z  s   zTensorProduct.__new__c                   s   t | t|  }t }||krt dg||    dd | jD fddttd D } fddtdg| |dg D  dd t| j D }t| S )	a  Apply on a list of fields.

        If the number of input fields supplied is not equal to the order of
        the tensor product field, the list of arguments is padded with ``None``'s.

        The list of arguments is divided in sublists depending on the order of
        the forms inside the tensor product. The sublists are provided as
        arguments to these forms and the resulting expressions are given to the
        constructor of ``TensorProduct``.

        Nc                 S  s   g | ]
}t |t| qS r-   rC  r  r-   r-   r.   rN   t  rR   z*TensorProduct.__call__.<locals>.<listcomp>c                   s    g | ]}t  d |d  qS r6   sumrJ   )ordersr-   r.   rN   u  rF  r7   c                   s   g | ]
\}} || qS r-   r-   )rK   rL   r@  )r  r-   r.   rN   v  rR   r   c                 S  s   g | ]}|d  j |d  qS r   r>  r   r-   r-   r.   rN   w  s    )r  r  r   r   _argsr]   r   rB  )r4   r  	tot_ordertot_argsindicesmultipliersr-   )r  rK  r.   r  d  s   $zTensorProduct.__call__)r8   r9   r:   r;   r#   r  r=   r-   r-   r+   r.   rB  $  s    5
rB  c                   @  s   e Zd ZdZdd ZdS )WedgeProducta  Wedge product of forms.

    Explanation
    ===========

    In the context of integration only completely antisymmetric forms make
    sense. The wedge product permits the creation of such forms.

    Examples
    ========

    >>> from sympy.diffgeom.rn import R2_r
    >>> from sympy.diffgeom import WedgeProduct

    >>> fx, fy = R2_r.base_scalars()
    >>> e_x, e_y = R2_r.base_vectors()
    >>> dx, dy = R2_r.base_oneforms()

    >>> WedgeProduct(dx, dy)(e_x, e_y)
    1
    >>> WedgeProduct(dx, dy)(e_y, e_x)
    -1
    >>> WedgeProduct(dx, fx*dy)(fx*e_x, e_y)
    x**2
    >>> WedgeProduct(e_x, e_y)(fy, None)
    -e_x

    You can nest wedge products.

    >>> wp1 = WedgeProduct(dx, dy)
    >>> WedgeProduct(wp1, dx)(e_x, e_y, e_x)
    0

    c                   sr   dd | j D }dtdd |D   }t|}dd ttt|D }t| j   |t fddt||D   S )z{Apply on a list of vector_fields.
        The expression is rewritten internally in terms of tensor products and evaluated.c                 s  s     | ]}t |t| V  qd S rC   rC  r   r-   r-   r.   rv     r   z(WedgeProduct.__call__.<locals>.<genexpr>r7   c                 s      | ]}t |V  qd S rC   r   rK   or-   r-   r.   rv     r   c                 s  s    | ]	}t | V  qd S rC   )r   rc   rK   pr-   r-   r.   rv     s    
c                   s    g | ]} |d   |d  qS r   r-   rV  tensor_prodr-   r.   rN     rF  z)WedgeProduct.__call__.<locals>.<listcomp>)r2   r   r   r]   r   rB  r   r   )r4   r  rK  mulperms	perms_parr-   rX  r.   r    s   
 zWedgeProduct.__call__N)r8   r9   r:   r;   r  r-   r-   r-   r.   rR  {  s    $rR  c                      r  )
LieDerivativea;  Lie derivative with respect to a vector field.

    Explanation
    ===========

    The transport operator that defines the Lie derivative is the pushforward of
    the field to be derived along the integral curve of the field with respect
    to which one derives.

    Examples
    ========

    >>> from sympy.diffgeom.rn import R2_r, R2_p
    >>> from sympy.diffgeom import (LieDerivative, TensorProduct)

    >>> fx, fy = R2_r.base_scalars()
    >>> e_x, e_y = R2_r.base_vectors()
    >>> e_rho, e_theta = R2_p.base_vectors()
    >>> dx, dy = R2_r.base_oneforms()

    >>> LieDerivative(e_x, fy)
    0
    >>> LieDerivative(e_x, fx)
    1
    >>> LieDerivative(e_x, e_x)
    0

    The Lie derivative of a tensor field by another tensor field is equal to
    their commutator:

    >>> LieDerivative(e_x, e_rho)
    Commutator(e_x, e_rho)
    >>> LieDerivative(e_x + e_y, fx)
    1

    >>> tp = TensorProduct(dx, dy)
    >>> LieDerivative(e_x, tp)
    LieDerivative(e_x, TensorProduct(dx, dy))
    >>> LieDerivative(e_x, tp)
    LieDerivative(e_x, TensorProduct(dx, dy))

    c                   sj   t |}t|dkst |rtd|dkr&t | ||}||_||_|S |tr0t	||S |
|S )Nr7   zmLie derivatives are defined only with respect to vector fields. The supplied argument was not a vector field.r   )r  r  r   r"   r#   _v_field_exprr  r   r  r>  )r&   v_fieldrd   expr_form_ordr*   r+   r-   r.   r#     s   


zLieDerivative.__new__c                 C  r/   r0   r1   r3   r-   r-   r.   r`    r5   zLieDerivative.v_fieldc                 C  r/   r6   r1   r3   r-   r-   r.   rd     r5   zLieDerivative.exprc                   s@   | j | j}|  }t fddtt D  }|| S )Nc                   s<   g | ]}t  d | t | f  |d d    qS r6   )r   r  rJ   r2   rq   r-   r.   rN     s    4z*LieDerivative.__call__.<locals>.<listcomp>)r`  rd   r   r]   r   )r4   r2   rd   	lead_termrestr-   rb  r.   r    s   
zLieDerivative.__call__)
r8   r9   r:   r;   r#   r<   r`  rd   r  r=   r-   r-   r+   r.   r]    s    *

r]  c                      sL   e Zd ZdZ fddZedd Zedd Zedd	 Zd
d Z	  Z
S )BaseCovarDerivativeOpas  Covariant derivative operator with respect to a base vector.

    Examples
    ========

    >>> from sympy.diffgeom.rn import R2_r
    >>> from sympy.diffgeom import BaseCovarDerivativeOp
    >>> from sympy.diffgeom import metric_to_Christoffel_2nd, TensorProduct

    >>> TP = TensorProduct
    >>> fx, fy = R2_r.base_scalars()
    >>> e_x, e_y = R2_r.base_vectors()
    >>> dx, dy = R2_r.base_oneforms()

    >>> ch = metric_to_Christoffel_2nd(TP(dx, dx) + TP(dy, dy))
    >>> ch
    [[[0, 0], [0, 0]], [[0, 0], [0, 0]]]
    >>> cvd = BaseCovarDerivativeOp(R2_r, 0, ch)
    >>> cvd(fx)
    1
    >>> cvd(fx*e_x)
    e_x
    c                   s8   t |}t|}t | |||}||_||_||_|S rC   )r   r   r"   r#   r   r   _christoffel)r&   r   r   christoffelr*   r+   r-   r.   r#     s   zBaseCovarDerivativeOp.__new__c                 C  r/   r0   r1   r3   r-   r-   r.   r     r5   zBaseCovarDerivativeOp.coord_sysc                 C  r/   r6   r1   r3   r-   r-   r.   r      r5   zBaseCovarDerivativeOp.indexc                 C  r/   r   r1   r3   r-   r-   r.   rg  $  r5   z!BaseCovarDerivativeOp.christoffelc           	        s
  t |dkr	t t| j} j j j jt|t	}fddt
|D }|tt||}|}|tt||}g }|D ]t fddtjjD  }|| qKfdd|D }|tt||}|tt||}| S )zApply on a scalar field.

        The action of a vector field on a scalar field is a directional
        differentiation.
        If the argument is not a scalar field the behaviour is undefined.
        r   c                   r  r  r  r  )
wrt_scalarr-   r.   rN   ;  r  z2BaseCovarDerivativeOp.__call__.<locals>.<listcomp>c                   s,   g | ]} j |jjf j| qS r-   )rf  r   r   r   rK   rp   )r4   rq   
wrt_vectorr-   r.   rN   F  s
    
c                      g | ]} |qS r-   r-   rK   d)rj  r-   r.   rN   J  r[   )r  r   vectors_in_basisr   r   r   r   r   r  r   rx   r   r   r   r]   r(   r@   r   )	r4   fieldvectorsr  r  derivsrm  to_subsr   r-   )r4   rq   rh  rj  r.   r  (  s,   

zBaseCovarDerivativeOp.__call__)r8   r9   r:   r;   r#   r<   r   r   rg  r  r=   r-   r-   r+   r.   re    s    



re  c                      r  )
CovarDerivativeOpaN  Covariant derivative operator.

    Examples
    ========

    >>> from sympy.diffgeom.rn import R2_r
    >>> from sympy.diffgeom import CovarDerivativeOp
    >>> from sympy.diffgeom import metric_to_Christoffel_2nd, TensorProduct
    >>> TP = TensorProduct
    >>> fx, fy = R2_r.base_scalars()
    >>> e_x, e_y = R2_r.base_vectors()
    >>> dx, dy = R2_r.base_oneforms()
    >>> ch = metric_to_Christoffel_2nd(TP(dx, dx) + TP(dy, dy))

    >>> ch
    [[[0, 0], [0, 0]], [[0, 0], [0, 0]]]
    >>> cvd = CovarDerivativeOp(fx*e_x, ch)
    >>> cvd(fx)
    x
    >>> cvd(fx*e_x)
    x*e_x

    c                   sf   t dd |tD dkrt t|dkst|rtdt|}t 	| ||}||_
||_|S )Nc                 S  r  r-   r  r   r-   r-   r.   r  n  r  z,CovarDerivativeOp.__new__.<locals>.<setcomp>r7   zsCovariant derivatives are defined only with respect to vector fields. The supplied argument was not a vector field.)r   r  r   r   r  r  r   r   r"   r#   _wrtrf  )r&   wrtrg  r*   r+   r-   r.   r#   m  s   zCovarDerivativeOp.__new__c                 C  r/   r0   r1   r3   r-   r-   r.   ru  {  r5   zCovarDerivativeOp.wrtc                 C  r/   r6   r1   r3   r-   r-   r.   rg    r5   zCovarDerivativeOp.christoffelc                   s>   t  jt} fdd|D } jt t|||S )Nc                   s   g | ]}t |j|j jqS r-   )re  r   r   rf  r   r3   r-   r.   rN         z.CovarDerivativeOp.__call__.<locals>.<listcomp>)r   rt  r  r   r   r   r>  )r4   ro  rp  base_opsr-   r3   r.   r    s
   
zCovarDerivativeOp.__call__)
r8   r9   r:   r;   r#   r<   ru  rg  r  r=   r-   r-   r+   r.   rs  T  s    

rs     NFc                   s   t dks
trtdfdd  fdd|r!|nj}| }fdd|D }|r<d	d t| D S td
d |D S )a
  Return the series expansion for an integral curve of the field.

    Explanation
    ===========

    Integral curve is a function `\gamma` taking a parameter in `R` to a point
    in the manifold. It verifies the equation:

    `V(f)\big(\gamma(t)\big) = \frac{d}{dt}f\big(\gamma(t)\big)`

    where the given ``vector_field`` is denoted as `V`. This holds for any
    value `t` for the parameter and any scalar field `f`.

    This equation can also be decomposed of a basis of coordinate functions
    `V(f_i)\big(\gamma(t)\big) = \frac{d}{dt}f_i\big(\gamma(t)\big) \quad \forall i`

    This function returns a series expansion of `\gamma(t)` in terms of the
    coordinate system ``coord_sys``. The equations and expansions are necessarily
    done in coordinate-system-dependent way as there is no other way to
    represent movement between points on the manifold (i.e. there is no such
    thing as a difference of points for a general manifold).

    Parameters
    ==========
    vector_field
        the vector field for which an integral curve will be given

    param
        the argument of the function `\gamma` from R to the curve

    start_point
        the point which corresponds to `\gamma(0)`

    n
        the order to which to expand

    coord_sys
        the coordinate system in which to expand
        coeffs (default False) - if True return a list of elements of the expansion

    Examples
    ========

    Use the predefined R2 manifold:

    >>> from sympy.abc import t, x, y
    >>> from sympy.diffgeom.rn import R2_p, R2_r
    >>> from sympy.diffgeom import intcurve_series

    Specify a starting point and a vector field:

    >>> start_point = R2_r.point([x, y])
    >>> vector_field = R2_r.e_x

    Calculate the series:

    >>> intcurve_series(vector_field, t, start_point, n=3)
    Matrix([
    [t + x],
    [    y]])

    Or get the elements of the expansion in a list:

    >>> series = intcurve_series(vector_field, t, start_point, n=3, coeffs=True)
    >>> series[0]
    Matrix([
    [x],
    [y]])
    >>> series[1]
    Matrix([
    [t],
    [0]])
    >>> series[2]
    Matrix([
    [0],
    [0]])

    The series in the polar coordinate system:

    >>> series = intcurve_series(vector_field, t, start_point,
    ...             n=3, coord_sys=R2_p, coeffs=True)
    >>> series[0]
    Matrix([
    [sqrt(x**2 + y**2)],
    [      atan2(y, x)]])
    >>> series[1]
    Matrix([
    [t*x/sqrt(x**2 + y**2)],
    [   -t*y/(x**2 + y**2)]])
    >>> series[2]
    Matrix([
    [t**2*(-x**2/(x**2 + y**2)**(3/2) + 1/sqrt(x**2 + y**2))/2],
    [                                t**2*x*y/(x**2 + y**2)**2]])

    See Also
    ========

    intcurve_diffequ

    r7   *The supplied field was not a vector field.c                   s   t dd  g| | S )z=Return ``vector_field`` called `i` times on ``scalar_field``.c                 S  r   rC   rL  )rn   rq   r-   r-   r.   r     s   
 z6intcurve_series.<locals>.iter_vfield.<locals>.<lambda>r   )r  rL   )vector_fieldr-   r.   iter_vfield  s   z$intcurve_series.<locals>.iter_vfieldc                   s    fddt D S )z-Return the series for one of the coordinates.c                   s,   g | ]}|  |  t| qS r-   )r>  r   rJ   )r   r{  paramstart_pointr-   r.   rN         $zCintcurve_series.<locals>.taylor_terms_per_coord.<locals>.<listcomp>)r]   r   )r{  rQ   r|  r}  r  r.   taylor_terms_per_coord  s   z/intcurve_series.<locals>.taylor_terms_per_coordc                   rk  r-   r-   r  )r  r-   r.   rN     r[   z#intcurve_series.<locals>.<listcomp>c                 S  rY   r-   )r{   r   r-   r-   r.   rN     r[   c                 S  rY   r-   rI  )rK   rA  r-   r-   r.   rN     r[   )r  r  r   r   r   r   r{   )rz  r|  r}  rQ   r   coeffsr   taylor_termsr-   )r{  rQ   r|  r}  r  rz  r.   intcurve_series  s   er  c                   s   t dks
trtd|r|nj}fddtjjD }t|| | } fdd|D } fdd|D }||fS )a5  Return the differential equation for an integral curve of the field.

    Explanation
    ===========

    Integral curve is a function `\gamma` taking a parameter in `R` to a point
    in the manifold. It verifies the equation:

    `V(f)\big(\gamma(t)\big) = \frac{d}{dt}f\big(\gamma(t)\big)`

    where the given ``vector_field`` is denoted as `V`. This holds for any
    value `t` for the parameter and any scalar field `f`.

    This function returns the differential equation of `\gamma(t)` in terms of the
    coordinate system ``coord_sys``. The equations and expansions are necessarily
    done in coordinate-system-dependent way as there is no other way to
    represent movement between points on the manifold (i.e. there is no such
    thing as a difference of points for a general manifold).

    Parameters
    ==========

    vector_field
        the vector field for which an integral curve will be given

    param
        the argument of the function `\gamma` from R to the curve

    start_point
        the point which corresponds to `\gamma(0)`

    coord_sys
        the coordinate system in which to give the equations

    Returns
    =======

    a tuple of (equations, initial conditions)

    Examples
    ========

    Use the predefined R2 manifold:

    >>> from sympy.abc import t
    >>> from sympy.diffgeom.rn import R2, R2_p, R2_r
    >>> from sympy.diffgeom import intcurve_diffequ

    Specify a starting point and a vector field:

    >>> start_point = R2_r.point([0, 1])
    >>> vector_field = -R2.y*R2.e_x + R2.x*R2.e_y

    Get the equation:

    >>> equations, init_cond = intcurve_diffequ(vector_field, t, start_point)
    >>> equations
    [f_1(t) + Derivative(f_0(t), t), -f_0(t) + Derivative(f_1(t), t)]
    >>> init_cond
    [f_0(0), f_1(0) - 1]

    The series in the polar coordinate system:

    >>> equations, init_cond = intcurve_diffequ(vector_field, t, start_point, R2_p)
    >>> equations
    [Derivative(f_0(t), t), Derivative(f_1(t), t) - 1]
    >>> init_cond
    [f_0(0) - 1, f_1(0) - pi/2]

    See Also
    ========

    intcurve_series

    r7   ry  c                   s   g | ]
}t d |  qS )zf_%dr  rJ   )r|  r-   r.   rN   U  rR   z$intcurve_diffequ.<locals>.<listcomp>c                   s0   g | ]}t t| |  qS r-   )r   r   r>  rK   cf)arbitrary_pr|  rz  r-   r.   rN   Y  s    (c                   s,   g | ]}t | d | qS r   )r   r>  r   r  )r  r|  r}  r-   r.   rN   [  r~  )r  r  r   r   r]   r(   r   r   )rz  r|  r}  r   gammasr   	equations	init_condr-   )r  r|  r}  rz  r.   intcurve_diffequ  s   L
r  c                   s>   t dd | D }tt| | t  fdd|D }||fS )Nc                 S  r   r-   r   r   r-   r-   r.   rN   e  r[   zdummyfy.<locals>.<listcomp>c                   s   g | ]	}t | qS r-   )r   r   )rK   rd   repsr-   r.   rN   g  r'  )r{   r   r   )r2   r   d_argsd_exprsr-   r  r.   r   c  s   r   c                 C  s   t | trdd | jD }tt|dkrtd|d S t | trCdd | jD }dd |D }t|dkr;td|s?dS |d S t | trXt| j	sRt| j
rVtd	dS t | tr_dS t | trntd
d | jD S |ru| trwdS dS )a`  Return the contravariant order of an expression.

    Examples
    ========

    >>> from sympy.diffgeom import contravariant_order
    >>> from sympy.diffgeom.rn import R2
    >>> from sympy.abc import a

    >>> contravariant_order(a)
    0
    >>> contravariant_order(a*R2.x + 2)
    0
    >>> contravariant_order(a*R2.x*R2.e_y + R2.e_x)
    1

    c                 S  rY   r-   r  r   r-   r-   r.   rN     r[   z'contravariant_order.<locals>.<listcomp>r7   zFMisformed expression containing contravariant fields of varying order.r   c                 S  rY   r-   r  r   r-   r-   r.   rN     r[   c                 S     g | ]}|d kr|qS r   r-   rT  r-   r-   r.   rN     rX   z?Misformed expression containing multiplication between vectors.z4Misformed expression containing a power of a vector.c                 s  rS  rC   r  r;  r-   r-   r.   rv     r   z&contravariant_order.<locals>.<genexpr>rz   )r!   r   r2   r   r  r   r   r   r  baseexpr   rB  rJ  r  r   rd   _strictrK  not_zeror-   r-   r.   r  m  s0   




r  c                 C  s   t | trdd | jD }tt|dkrtd|d S t | trCdd | jD }dd |D }t|dkr;td|s?dS |d S t | trXt| j	sRt| j
rVtd	dS t | trdt| j d S t | trstd
d | jD S |rz| tr|dS dS )aJ  Return the covariant order of an expression.

    Examples
    ========

    >>> from sympy.diffgeom import covariant_order
    >>> from sympy.diffgeom.rn import R2
    >>> from sympy.abc import a

    >>> covariant_order(a)
    0
    >>> covariant_order(a*R2.x + 2)
    0
    >>> covariant_order(a*R2.x*R2.dy + R2.dx)
    1

    c                 S  rY   r-   r  r   r-   r-   r.   rN     r[   z#covariant_order.<locals>.<listcomp>r7   z=Misformed expression containing form fields of varying order.r   c                 S  rY   r-   r  r   r-   r-   r.   rN     r[   c                 S  r  r   r-   rT  r-   r-   r.   rN     rX   z=Misformed expression containing multiplication between forms.z2Misformed expression containing a power of a form.c                 s  rS  rC   r  r;  r-   r-   r.   rv     r   z"covariant_order.<locals>.<genexpr>rz   )r!   r   r2   r   r  r   r   r   r  r  r  r   rB  rJ  r  r   r  r-   r-   r.   r    s0   




r  c                 C  sh   t | t}g }|D ]}|j}||| }|jt|  |j	 }|
| q| t t||S )a  Transform all base vectors in base vectors of a specified coord basis.
    While the new base vectors are in the new coordinate system basis, any
    coefficients are kept in the old system.

    Examples
    ========

    >>> from sympy.diffgeom import vectors_in_basis
    >>> from sympy.diffgeom.rn import R2_r, R2_p

    >>> vectors_in_basis(R2_r.e_x, R2_p)
    -y*e_theta/(x**2 + y**2) + x*e_rho/sqrt(x**2 + y**2)
    >>> vectors_in_basis(R2_p.e_r, R2_r)
    sin(theta)*e_y + cos(theta)*e_x

    )r   r  r   r   r   r   Tr{   r   r   r@   r   r   )rd   r   rp  new_vectorsrq   csr  newr-   r-   r.   rn    s   rn  c                   sl   t  dks
t rtdt }t|dkrtd| }|     fddD }t|S )a  Return the matrix representing the twoform.

    For the twoform `w` return the matrix `M` such that `M[i,j]=w(e_i, e_j)`,
    where `e_i` is the i-th base vector field for the coordinate system in
    which the expression of `w` is given.

    Examples
    ========

    >>> from sympy.diffgeom.rn import R2
    >>> from sympy.diffgeom import twoform_to_matrix, TensorProduct
    >>> TP = TensorProduct

    >>> twoform_to_matrix(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy))
    Matrix([
    [1, 0],
    [0, 1]])
    >>> twoform_to_matrix(R2.x*TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy))
    Matrix([
    [x, 0],
    [0, 1]])
    >>> twoform_to_matrix(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy) - TP(R2.dx, R2.dy)/2)
    Matrix([
    [   1, 0],
    [-1/2, 1]])

    rw   z'The input expression is not a two-form.r7   zThe input expression concerns more than one coordinate systems, hence there is no unambiguous way to choose a coordinate system for the matrix.c                   s    g | ]  fd dD qS )c                   s   g | ]}  |qS r-   rL  )rK   r&  )rd   r)  r-   r.   rN     rX   z0twoform_to_matrix.<locals>.<listcomp>.<listcomp>r-   rK   rd   rp  r(  r.   rN     s    z%twoform_to_matrix.<locals>.<listcomp>)	r  r  r   r  r   popr   r#  r{   )rd   r   matrix_contentr-   r  r.   twoform_to_matrix  s   r  c                   sd   t |  stdt|  }fdd| D  tt|j fddD }t	|S )aX  Return the nested list of Christoffel symbols for the given metric.
    This returns the Christoffel symbol of first kind that represents the
    Levi-Civita connection for the given metric.

    Examples
    ========

    >>> from sympy.diffgeom.rn import R2
    >>> from sympy.diffgeom import metric_to_Christoffel_1st, TensorProduct
    >>> TP = TensorProduct

    >>> metric_to_Christoffel_1st(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy))
    [[[0, 0], [0, 0]], [[0, 0], [0, 0]]]
    >>> metric_to_Christoffel_1st(R2.x*TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy))
    [[[1/2, 0], [0, 0]], [[0, 0], [0, 0]]]

    z6The two-form representing the metric is not symmetric.c                   r   r-   )	applyfuncrl  )matrixr-   r.   rN   ,  r   z-metric_to_Christoffel_1st.<locals>.<listcomp>c                   s"   g | ]  fd dD qS )c                   s"   g | ]  fd dD qS )c                   s@   g | ]} | f   |f    |f  d  qS )rw   r-   ri  )deriv_matricesrL   r@  r-   r.   rN   .  s    8zCmetric_to_Christoffel_1st.<locals>.<listcomp>.<listcomp>.<listcomp>r-   r  )r  rL   rP  r@  r.   rN   .  
    
z8metric_to_Christoffel_1st.<locals>.<listcomp>.<listcomp>r-   r  )r  rP  rL   r.   rN   .  s
    
)
r  is_symmetricr   r  r  r   r   r]   r(   r   )rd   r   rg  r-   )r  rP  r  r.   metric_to_Christoffel_1st  s   r  c                   s   t |  t|  }tt|jt| t }D ]
}||	t
 qt|}|j}tt|| tt|| fddD }t|S )a]  Return the nested list of Christoffel symbols for the given metric.
    This returns the Christoffel symbol of second kind that represents the
    Levi-Civita connection for the given metric.

    Examples
    ========

    >>> from sympy.diffgeom.rn import R2
    >>> from sympy.diffgeom import metric_to_Christoffel_2nd, TensorProduct
    >>> TP = TensorProduct

    >>> metric_to_Christoffel_2nd(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy))
    [[[0, 0], [0, 0]], [[0, 0], [0, 0]]]
    >>> metric_to_Christoffel_2nd(R2.x*TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy))
    [[[1/(2*x), 0], [0, 0]], [[0, 0], [0, 0]]]

    c                   s$   g | ]  fd dD qS )c                   s&   g | ]  fd dD qS )c                   s*   g | ] t  fd dD  qS )c                   s&   g | ]}|f  |f  qS r-   r-   rK   l)ch_1strL   r@  rp   r  r-   r.   rN   U  s   & zNmetric_to_Christoffel_2nd.<locals>.<listcomp>.<listcomp>.<listcomp>.<listcomp>r   r  )r  rL   rP  r@  r  rp   r.   rN   U      "zCmetric_to_Christoffel_2nd.<locals>.<listcomp>.<listcomp>.<listcomp>r-   r  )r  rL   rP  r  r  r.   rN   U  
    
z8metric_to_Christoffel_2nd.<locals>.<listcomp>.<listcomp>r-   r  r  rP  r  r  r.   rN   U  
    
z-metric_to_Christoffel_2nd.<locals>.<listcomp>)r  r  r  r   r]   r(   r  r  updater  r   rk   r   r   invr   )rd   r   s_fieldsr   dumsrg  r-   r  r.   metric_to_Christoffel_2nd5  s   (r  c                   s~   t |  t|  ttj fddD fddD  fddD fddD }t|S )a!  Return the components of the Riemann tensor expressed in a given basis.

    Given a metric it calculates the components of the Riemann tensor in the
    canonical basis of the coordinate system in which the metric expression is
    given.

    Examples
    ========

    >>> from sympy import exp
    >>> from sympy.diffgeom.rn import R2
    >>> from sympy.diffgeom import metric_to_Riemann_components, TensorProduct
    >>> TP = TensorProduct

    >>> metric_to_Riemann_components(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy))
    [[[[0, 0], [0, 0]], [[0, 0], [0, 0]]], [[[0, 0], [0, 0]], [[0, 0], [0, 0]]]]
    >>> non_trivial_metric = exp(2*R2.r)*TP(R2.dr, R2.dr) +         R2.r**2*TP(R2.dtheta, R2.dtheta)
    >>> non_trivial_metric
    exp(2*rho)*TensorProduct(drho, drho) + rho**2*TensorProduct(dtheta, dtheta)
    >>> riemann = metric_to_Riemann_components(non_trivial_metric)
    >>> riemann[0, :, :, :]
    [[[0, 0], [0, 0]], [[0, exp(-2*rho)*rho], [-exp(-2*rho)*rho, 0]]]
    >>> riemann[1, :, :, :]
    [[[0, -1/rho], [1/rho, 0]], [[0, 0], [0, 0]]]

    c                   s$   g | ]  fd dD qS )c                   s$   g | ]  fd dD qS )c                   s(   g | ]  fd d  D qS )c                   s   g | ]}| f qS r-   r-   rl  )ch_2ndrL   r@  rp   r-   r.   rN   {  rv  Qmetric_to_Riemann_components.<locals>.<listcomp>.<listcomp>.<listcomp>.<listcomp>)r   r  )r  r   rL   r@  r  r.   rN   {  s
    
Fmetric_to_Riemann_components.<locals>.<listcomp>.<listcomp>.<listcomp>r-   r  )r  r   rL   rP  r  r.   rN   {  r  ;metric_to_Riemann_components.<locals>.<listcomp>.<listcomp>r-   r  )r  r   rP  r  r.   rN   {  
    
z0metric_to_Riemann_components.<locals>.<listcomp>c                   "   g | ]  fd dD qS )c                   $   g | ]  fd dD qS )c                   s$   g | ]  fd dD qS )c                   s4   g | ]}   |      |  qS r-   r-   rK   nu)deriv_chmurhosigr-   r.   rN         ,r  r-   r  )r  rP  r  r  r  r.   rN     s
    
r  r-   r  )r  rP  r  r  r.   rN     r  r  r-   r  )r  rP  r  r.   rN     
    
c                   r  )c                   r  )c                   s&   g | ]  fd dD qS )c                   s*   g | ] t  fd dD  qS )c                   sD   g | ]} |f  |f   |f  |f   qS r-   r-   r  )r  r  r  r  r  r-   r.   rN     s   D z\metric_to_Riemann_components.<locals>.<listcomp>.<listcomp>.<listcomp>.<listcomp>.<listcomp>r  r  )r  rP  r  r  r  )r  r.   rN     r  r  r-   r  )r  rP  r  r  r  r.   rN     r  r  r-   r  )r  rP  r  r  r.   rN     r  r  r-   r  )r  rP  r  r.   rN     r  c                   s$   g | ]  fd dD qS )c                   s&   g | ]  fd dD qS )c                   s&   g | ]  fd dD qS )c                   s4   g | ]}    |     |  qS r-   r-   r  )r  r  	riemann_a	riemann_br  r-   r.   rN     r  r  r-   r  )rP  r  r  r  r  r  r.   rN     r  r  r-   r  )rP  r  r  r  r  r.   rN     s
    
r  r-   r  )rP  r  r  r  r.   rN     r  )r  r  r  r   r]   r(   r   )rd   riemannr-   )r  r   r  rP  r  r  r.   metric_to_Riemann_components\  s    r  c                   s>   t | t|  }tt|j  fdd D }t|S )a]  Return the components of the Ricci tensor expressed in a given basis.

    Given a metric it calculates the components of the Ricci tensor in the
    canonical basis of the coordinate system in which the metric expression is
    given.

    Examples
    ========

    >>> from sympy import exp
    >>> from sympy.diffgeom.rn import R2
    >>> from sympy.diffgeom import metric_to_Ricci_components, TensorProduct
    >>> TP = TensorProduct

    >>> metric_to_Ricci_components(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy))
    [[0, 0], [0, 0]]
    >>> non_trivial_metric = exp(2*R2.r)*TP(R2.dr, R2.dr) +                              R2.r**2*TP(R2.dtheta, R2.dtheta)
    >>> non_trivial_metric
    exp(2*rho)*TensorProduct(drho, drho) + rho**2*TensorProduct(dtheta, dtheta)
    >>> metric_to_Ricci_components(non_trivial_metric)
    [[1/rho, 0], [0, exp(-2*rho)*rho]]

    c                   s"   g | ]  fd dD qS )c                   s&   g | ] t  fd dD  qS )c                   s   g | ]
}| |f qS r-   r-   ri  )rL   r@  r  r-   r.   rN     rR   zDmetric_to_Ricci_components.<locals>.<listcomp>.<listcomp>.<listcomp>r  r  )rL   rP  r  r  r.   rN     s    z9metric_to_Ricci_components.<locals>.<listcomp>.<listcomp>r-   r  rP  r  r  r.   rN     r  z.metric_to_Ricci_components.<locals>.<listcomp>)r  r  r  r   r]   r(   r   )rd   r   riccir-   r  r.   metric_to_Ricci_components  s   r  c                      sH   e Zd Z fddZdd Z fddZ fddZ fd	d
Z  ZS )_deprecated_containerc                   s   t  | || _d S rC   )r"   __init__message)r4   r  datar+   r-   r.   r    s   
z_deprecated_container.__init__c                 C  s   t | jdddd d S )NrS   rT      )rV   rW   
stacklevel)r   r  r3   r-   r-   r.   warn  s   
z_deprecated_container.warnc                   s   |    t  S rC   )r  r"   __iter__r3   r+   r-   r.   r    s   
z_deprecated_container.__iter__c                      |    t |S rC   )r  r"   __getitem__r4   rt   r+   r-   r.   r       z!_deprecated_container.__getitem__c                   r  rC   )r  r"   __contains__r  r+   r-   r.   r    r  z"_deprecated_container.__contains__)	r8   r9   r:   r  r  r  r  r  r=   r-   r-   r+   r.   r    s    r  c                   @     e Zd ZdS )r$   Nr8   r9   r:   r-   r-   r-   r.   r$         r$   c                   @  r  )re   Nr  r-   r-   r-   r.   re     r  re   )r   )rx  NFrC   )F)L
__future__r   typingr   	functoolsr   	itertoolsr   sympy.combinatoricsr   
sympy.corer   r	   r
   r   r   r   r   r   r   r   r   sympy.core.cacher   sympy.core.symbolr   r   r   sympy.core.sympifyr   sympy.functionsr   sympy.matricesr   r{   sympy.solversr   sympy.utilities.exceptionsr   r   r   sympy.tensor.arrayr   r    r>   rF   ru   r   r   r   r  r  r   rB  rR  r]  re  rs  r  r  r   r  r  rn  r  r  r  r  r  r  r   r$   r   re   sympy.simplify.simplifyr   r-   r-   r-   r.   <module>   sb    4	<F    ANSe|NnW1M[
9
y]


.1+ '6&