
    \hZC                         S /r SSKJrJrJr  SSKJr  SSKJr  SSK	J
r
  SSKJrJr  SSKJr  SSKJr   " S	 S 5      rS
 rg)
Linearizer    )Matrixeyezeros)Dummy)flatten)dynamicsymbols)msubs_parse_linear_solver)
namedtuple)Iterablec                   J    \ rS rSrSr   SS jrS rS rS rS r	SS	 jr
S
rg)r      a  This object holds the general model form for a dynamic system. This
model is used for computing the linearized form of the system, while
properly dealing with constraints leading to  dependent coordinates and
speeds. The notation and method is described in [1]_.

Attributes
==========

f_0, f_1, f_2, f_3, f_4, f_c, f_v, f_a : Matrix
    Matrices holding the general system form.
q, u, r : Matrix
    Matrices holding the generalized coordinates, speeds, and
    input vectors.
q_i, u_i : Matrix
    Matrices of the independent generalized coordinates and speeds.
q_d, u_d : Matrix
    Matrices of the dependent generalized coordinates and speeds.
perm_mat : Matrix
    Permutation matrix such that [q_ind, u_ind]^T = perm_mat*[q, u]^T

References
==========

.. [1] D. L. Peterson, G. Gede, and M. Hubbard, "Symbolic linearization of
       equations of motion of constrained multibody systems," Multibody
       Syst Dyn, vol. 33, no. 2, pp. 143-161, Feb. 2015, doi:
       10.1007/s11044-014-9436-5.

Nc                 p   [        U5      U l        [        U5      U l        [        U5      U l        [        U5      U l        [        U5      U l        [        U5      U l        [        U5      U l        [        U5      U l	        [        U5      U l
        [        U	5      U l        [        U
5      U l        S nU" U5      U l        U" U5      U l        U" U5      U l        U" U5      U l        U" U5      U l        U" U5      U l        U R                  R'                  [(        R*                  5      U l        U R                  R'                  [(        R*                  5      U l        [1        U R,                  5      R3                  U R                  5      n[        U R,                   Vs/ s H  nUU;  a  UO	[5        5       PM     sn5      U l        [9        U R                  5      n[9        U R                  5      n[9        U R                  5      n[9        U R                  5      n[9        U R"                  5      n[9        U R$                  5      n[;        S/ SQ5      nU" UUUUUU5      U l        SU l        SU l         SU l!        SU l"        SU l#        SU l$        SU l%        SU l&        SU l'        SU l(        SU l)        gs  snf )a  
Parameters
==========

f_0, f_1, f_2, f_3, f_4, f_c, f_v, f_a : array_like
    System of equations holding the general system form.
    Supply empty array or Matrix if the parameter
    does not exist.
q : array_like
    The generalized coordinates.
u : array_like
    The generalized speeds
q_i, u_i : array_like, optional
    The independent generalized coordinates and speeds.
q_d, u_d : array_like, optional
    The dependent generalized coordinates and speeds.
r : array_like, optional
    The input variables.
lams : array_like, optional
    The lagrange multipliers
linear_solver : str, callable
    Method used to solve the several symbolic linear systems of the
    form ``A*x=b`` in the linearization process. If a string is
    supplied, it should be a valid method that can be used with the
    :meth:`sympy.matrices.matrixbase.MatrixBase.solve`. If a callable is
    supplied, it should have the format ``x = f(A, b)``, where it
    solves the equations and returns the solution. The default is
    ``'LU'`` which corresponds to SymPy's ``A.LUsolve(b)``.
    ``LUsolve()`` is fast to compute but will often result in
    divide-by-zero and thus ``nan`` results.

c                 :    U (       a  [        U 5      $ [        5       $ )N)r   )xs    Y/var/www/auris/envauris/lib/python3.13/site-packages/sympy/physics/mechanics/linearize.py<lambda>%Linearizer.__init__.<locals>.<lambda>^   s    a!=VX!=    dims)lmnoskNF)*r   linear_solverr   f_0f_1f_2f_3f_4f_cf_vf_aquq_iq_du_iu_drlamsdiffr	   _t_qd_udsetintersectionr   _qd_duplenr   _dims_Pq_Pqi_Pqd_Pu_Pui_Pud_C_0_C_1_C_2perm_mat_setup_done)selfr   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r   none_handlerdup_varsvarr   r   r   r   r   r   r   s                               r   __init__Linearizer.__init__,   s%   F 2-@ #;#;#;#;#;#;#;#; =$$$$a &	 66;;~00166;;~001 txx=--dff5"&((,"* LOc&9suwF"*, - MMKKK		N&"@A!Q1a+
							 1,s   J3c                 r    U R                  5         U R                  5         U R                  5         SU l        g )NT)_form_permutation_matrices_form_block_matrices_form_coefficient_matricesrB   )rC   s    r   _setupLinearizer._setup   s0     	'')!!#'')r   c           	         U R                   u  pp4pVUS:w  a  [        U R                  [        U R                  U R
                  /5      5      U l        US:  a7  U R                  SS2SU* 24   U l        U R                  SS2U* S24   U l        O U R                  U l        [        5       U l        US:w  a  [        U R                  [        U R                  U R                  /5      5      U l        US:  a7  U R                  SS2SU* 24   U l        U R                  SS2U* S24   U l        O U R                  U l        [        5       U l        [        U R                  [        XF-   X1-
  5      /5      n[        [        X4U-
  5      U R                  [        XdU-
  5      /5      nU(       a%  U(       a  UR!                  U5      U l        gXpl        gXl        g)z(Form the permutation matrices Pq and Pu.r   N)r7   permutation_matrixr'   r   r)   r*   r8   r9   r:   r(   r+   r,   r;   r<   r=   r   row_joinrA   )	rC   r   r   r   r   r   r   P_col1P_col2s	            r   rJ   %Linearizer._form_permutation_matrices   sg     ::aA6)$&&&$((DHH9M2NODH1u HHQ!V,	 HHQV,	 HH	"H	6)$&&&$((DHH9M2NODH1u HHQ!V,	 HHQV,	 HH	"H	E!%$789qa%$))U1!e_EF & 7 &"Mr   c                    U R                   u  pp4pVUS:  ao  U R                  R                  U R                  5      n[	        U5      U R
                  U R                  XpR
                  -  U5      -  -
  U R                  -  U l        O[	        U5      U l        US:  a  U R                  R                  U R                  5      nXR                  -  n	US:w  aJ  U R                  R                  U R                  5      n
U R                  * U R                  X5      -  U l        O[        XC5      U l        [	        U5      U R                  U R                  X5      -  -
  U R                  -  U l        g[        XC5      U l        [	        U5      U l        g)z0Form the coefficient matrices C_0, C_1, and C_2.r   N)r7   r$   jacobianr'   r   r:   r   r9   r>   r%   r(   r=   r?   r   r<   r@   )rC   r   r   r   r   r   r   	f_c_jac_q	f_v_jac_utemp	f_v_jac_qs              r   rL   %Linearizer._form_coefficient_matrices   sF     ::aA q5))$&&1IQ$))++Iii,?,57#7 78<		BDI ADI q5))$&&1Iyy(DAv HH--dff5	!YYJ););D)LL	!!K	Q$))++D<#= =>BiiHDI aDIADIr   c                 P   U R                   u  pp4pVUS:w  ac  U R                  R                  U R                  5      U l        U R                  U R
                  -   R                  U R                  5      * U l        O[        5       U l        [        5       U l        US:w  a\  US:w  aV  U R                  R                  U R                  5      U l        U R                  R                  U R                  5      * U l        O[        5       U l        [        5       U l        US:w  a{  XB-
  U-   S:w  ap  U R                  R                  U R                  5      U l        U R                  U R                  -   U R                   -   R                  U R                  5      * U l        O[        5       U l        [        5       U l        US:w  a\  US:w  aV  U R                  R                  U R$                  5      U l        U R                  R                  U R(                  5      * U l        O[        5       U l        [        5       U l        US:w  an  XB-
  U-   S:w  ac  U R                  R                  U R$                  5      U l        U R                  U R                  -   R                  U R(                  5      * U l        O[        5       U l        [        5       U l        US:w  a2  US:w  a,  U R
                  R                  U R(                  5      * U l        O[        5       U l        US:w  a6  XB-
  U-   S:w  a+  U R                   R                  U R2                  5      U l        O[        5       U l        US:w  a7  XB-
  U-   S:w  a,  U R                  R                  U R6                  5      * U l        g[        5       U l        g)z2Form the block matrices for composing M, A, and B.r   N)r7   r   rV   r1   _M_qqr    r'   _A_qqr   r&   r5   _M_uqc_A_uqcr"   _M_uqdr!   r#   _A_uqdr2   _M_uucr(   _A_uuc_M_uud_A_uud_A_qur.   _M_uldr-   _B_u)rC   r   r   r   r   r   r   s          r   rK   Linearizer._form_block_matrices   s     ::aA 6**4884DJ88dhh.88@@DJDJDJ6a1f((++DLL9DK88,,TVV44DK (DK (DK6aeai1n((++DLL9DK HHtxx/$((:DDTVVLLDK (DK (DK6a1f((++DHH5DK88,,TVV44DK (DK (DK6aeai1n((++DHH5DK HHtxx/99$&&AADK (DK (DK6a1f((++DFF33DJDJ6aeai1n((++DII6DK (DK6aeai1n**46622DIDIr   c                 L   U R                   (       d  U R                  5         [        U[        5      (       a  UnO4[        U[        5      (       a  0 nU H  nUR                  U5        M     O0 nU R                  u  pgppU R                  nU R                  nU R                  nU R                  nU R                  nU R                  nU R                  nU R                  nU R                  nU R                   nU R"                  nU R$                  nU R&                  nU R(                  nU R*                  nU R,                  nU	S:w  a  [/        [1        X5      UU/5      nUS:w  a  [/        [1        X-   U5      U/5      nUS:w  aU  [/        XU/5      nU	S:w  a'  US:w  a!  UR3                  W5      R3                  W5      nO5U	S:w  a  UR3                  W5      nOUnOUS:w  a  WR3                  W5      nOWn[5        UU5      n US:w  au  Un!U	S:w  a  U!UU-  -  n!U!U-  n!US:w  a  Un"U	S:w  a  U"UU-  -  n"U"U-  n"O
[/        5       n"X-
  U-   S:w  a  Un#U	S:w  a  U#UU-  -  n#U#U-  n#O
[/        5       n#[/        U!U"U#/5      nO
[/        5       nU	S:w  aV  US:w  a  UU-  n$O
[/        5       n$US:w  a  UU-  n%O
[/        5       n%X-
  U-   S:w  a  UU-  n&O
[/        5       n&[/        U$U%U&/5      nO
[/        5       nU(       a  U(       a  UR3                  U5      n'OUn'OUn'[5        U'U5      n(U
S:w  a5  X-
  U-   S:w  a*  [1        X-   U
5      R7                  U5      n)[5        U)U5      n*O
[/        5       n*U(       a  U R8                  R:                  U R=                  U U(5      -  n+U*(       a*  U R8                  R:                  U R=                  U U*5      -  n,OU*n,U(       a   U+R?                  5         U,R?                  5         U+U,4$ U(       a0  U R?                  5         U(R?                  5         U*R?                  5         U U(U*4$ )a  Linearize the system about the operating point. Note that
q_op, u_op, qd_op, ud_op must satisfy the equations of motion.
These may be either symbolic or numeric.

Parameters
==========
op_point : dict or iterable of dicts, optional
    Dictionary or iterable of dictionaries containing the operating
    point conditions for all or a subset of the generalized
    coordinates, generalized speeds, and time derivatives of the
    generalized speeds. These will be substituted into the linearized
    system before the linearization is complete. Leave set to ``None``
    if you want the operating point to be an arbitrary set of symbols.
    Note that any reduction in symbols (whether substituted for numbers
    or expressions with a common parameter) will result in faster
    runtime.
A_and_B : bool, optional
    If A_and_B=False (default), (M, A, B) is returned and of
    A_and_B=True, (A, B) is returned. See below.
simplify : bool, optional
    Determines if returned values are simplified before return.
    For large expressions this may be time consuming. Default is False.

Returns
=======
M, A, B : Matrices, ``A_and_B=False``
    Matrices from the implicit form:
        ``[M]*[q', u']^T = [A]*[q_ind, u_ind]^T + [B]*r``
A, B : Matrices, ``A_and_B=True``
    Matrices from the explicit form:
        ``[q_ind', u_ind']^T = [A]*[q_ind, u_ind]^T + [B]*r``

Notes
=====

Note that the process of solving with A_and_B=True is computationally
intensive if there are many symbolic parameters. For this reason, it
may be more desirable to use the default A_and_B=False, returning M, A,
and B. More values may then be substituted in to these matrices later
on. The state space form can then be found as A = P.T*M.LUsolve(A), B =
P.T*M.LUsolve(B), where P = Linearizer.perm_mat.

r   ) rB   rM   
isinstancedictr   updater7   r]   r_   ra   rc   re   rh   r^   r`   rb   rg   rd   rf   ri   r>   r?   r@   r   r   rQ   r
   col_joinrA   Tr   simplify)-rC   op_pointA_and_Brq   op_point_dictopr   r   r   r   r   r   M_qqM_uqcM_uqdM_uucM_uudM_uldA_qqA_uqcA_uqdA_quA_uucA_uudB_uC_0C_1C_2col2col3col1MM_eqr1c1r2c1r3c1r1c2r2c2r3c2AmatAmat_eqBmatBmat_eqA_contB_conts-                                                r   	linearizeLinearizer.linearize  s   \ KKM h%%$M(++M$$R(  M  ::aA zzzzzziiiiiiii 65;u56D65?E23D64./DAv!q&MM$'006aMM$'!Vd#AAQ& 6DAv$#:DAv6US[)DczxuqyA~6US[)Dczx4t,-D8D6AvczxAvs{xuqyA~s{x4t,-D8D}}T*Dm,
 6aeai1n?++C0DD-0GhG ]]__t'9'9$'HHF4+=+=dG+LL !!!6>!   "  "'))r   )-r^   rg   r`   rb   rd   rf   ri   r>   r?   r@   r]   rh   r_   ra   rc   re   r8   r:   r9   r;   r=   r<   r7   r1   r5   rB   r2   r   r    r!   r"   r#   r&   r$   r%   r.   r   rA   r'   r*   r)   r-   r(   r,   r+   )NNNNNNLU)NFF)__name__
__module____qualname____firstlineno____doc__rG   rM   rJ   rL   rK   r   __static_attributes__ r   r   r   r      s8    < JN<@#Y!v #B@0!dx*r   c                    [        U [        [        45      (       d  [        U 5      n [        U[        [        45      (       d  [        U5      n[	        U 5      [	        U5      :w  a  [        S5      eU Vs/ s H  o R                  U5      PM     nn[        [        U 5      5      n[        U5       H  u  p%SXBU4'   M     U$ s  snf )a;  Compute the permutation matrix to change order of
orig_vec into order of per_vec.

Parameters
==========

orig_vec : array_like
    Symbols in original ordering.
per_vec : array_like
    Symbols in new ordering.

Returns
=======

p_matrix : Matrix
    Permutation matrix such that orig_vec == (p_matrix * per_vec).
zKorig_vec and per_vec must be the same length, and contain the same symbols.   )
rl   listtupler   r3   
ValueErrorindexr   r6   	enumerate)orig_vecper_veciind_listp_matrixjs         r   rP   rP     s    $ hu..8$ge}--'"
8}G$ 9 : 	:+237aq!7H3S]#H(#A $O	 4s   4C N)__all__sympyr   r   r   sympy.core.symbolr   sympy.utilities.iterablesr   sympy.physics.vectorr	   !sympy.physics.mechanics.functionsr
   r   collectionsr   collections.abcr   r   rP   r   r   r   <module>r      s6   . $ $ # - / I " $m* m*`r   