K iNddlmZmZmZmZmZddlmZddlm Z m Z ddl m Z ddl mZmZmZmZddlmZddlmZdgZGd de Zy ) )diffzerosMatrixeyesympify)default_sort_key)dynamicsymbolsReferenceFrame)_Methods)find_dynamicsymbolsmsubs_f_list_parser_validate_coordinates) Linearizer)iterableLagrangesMethodceZdZdZ ddZdZdZedZedZ edZ ed Z dd Z dd Z dd Zdd ZedZedZedZedZedZy)raLagrange's method object. Explanation =========== This object generates the equations of motion in a two step procedure. The first step involves the initialization of LagrangesMethod by supplying the Lagrangian and the generalized coordinates, at the bare minimum. If there are any constraint equations, they can be supplied as keyword arguments. The Lagrange multipliers are automatically generated and are equal in number to the constraint equations. Similarly any non-conservative forces can be supplied in an iterable (as described below and also shown in the example) along with a ReferenceFrame. This is also discussed further in the __init__ method. Attributes ========== q, u : Matrix Matrices of the generalized coordinates and speeds loads : iterable Iterable of (Point, vector) or (ReferenceFrame, vector) tuples describing the forces on the system. bodies : iterable Iterable containing the rigid bodies and particles of the system. mass_matrix : Matrix The system's mass matrix forcing : Matrix The system's forcing vector mass_matrix_full : Matrix The "mass matrix" for the qdot's, qdoubledot's, and the lagrange multipliers (lam) forcing_full : Matrix The forcing vector for the qdot's, qdoubledot's and lagrange multipliers (lam) Examples ======== This is a simple example for a one degree of freedom translational spring-mass-damper. In this example, we first need to do the kinematics. This involves creating generalized coordinates and their derivatives. Then we create a point and set its velocity in a frame. >>> from sympy.physics.mechanics import LagrangesMethod, Lagrangian >>> from sympy.physics.mechanics import ReferenceFrame, Particle, Point >>> from sympy.physics.mechanics import dynamicsymbols >>> from sympy import symbols >>> q = dynamicsymbols('q') >>> qd = dynamicsymbols('q', 1) >>> m, k, b = symbols('m k b') >>> N = ReferenceFrame('N') >>> P = Point('P') >>> P.set_vel(N, qd * N.x) We need to then prepare the information as required by LagrangesMethod to generate equations of motion. First we create the Particle, which has a point attached to it. Following this the lagrangian is created from the kinetic and potential energies. Then, an iterable of nonconservative forces/torques must be constructed, where each item is a (Point, Vector) or (ReferenceFrame, Vector) tuple, with the Vectors representing the nonconservative forces or torques. >>> Pa = Particle('Pa', P, m) >>> Pa.potential_energy = k * q**2 / 2.0 >>> L = Lagrangian(N, Pa) >>> fl = [(P, -b * qd * N.x)] Finally we can generate the equations of motion. First we create the LagrangesMethod object. To do this one must supply the Lagrangian, and the generalized coordinates. The constraint equations, the forcelist, and the inertial frame may also be provided, if relevant. Next we generate Lagrange's equations of motion, such that: Lagrange's equations of motion = 0. We have the equations of motion at this point. >>> l = LagrangesMethod(L, [q], forcelist = fl, frame = N) >>> print(l.form_lagranges_equations()) Matrix([[b*Derivative(q(t), t) + 1.0*k*q(t) + m*Derivative(q(t), (t, 2))]]) We can also solve for the states using the 'rhs' method. >>> print(l.rhs()) Matrix([[Derivative(q(t), t)], [(-b*Derivative(q(t), t) - 1.0*k*q(t))/m]]) Please refer to the docstrings on each method for more details. Nctt|g|_d|_t|_t|_t|_t|_t|_|r|ng}t|s td||_ |rt|ts td||_||_t|_t|_t|_t|_t|_t|s tdt||_|j,j/t0j2|_|j4j/t0j2|_t9|j,d}||}||}t|j/t0j2|g|_||_y)aSupply the following for the initialization of LagrangesMethod. Lagrangian : Sympifyable qs : array_like The generalized coordinates hol_coneqs : array_like, optional The holonomic constraint equations nonhol_coneqs : array_like, optional The nonholonomic constraint equations forcelist : iterable, optional Takes an iterable of (Point, Vector) or (ReferenceFrame, Vector) tuples which represent the force at a point or torque on a frame. This feature is primarily to account for the nonconservative forces and/or moments. bodies : iterable, optional Takes an iterable containing the rigid bodies and particles of the system. frame : ReferenceFrame, optional Supply the inertial frame. This is used to determine the generalized forces due to non-conservative forces. Nz,Force pairs must be supplied in an iterable.z$frame must be a valid ReferenceFramez+Generalized coordinates must be an iterablec0|r t|StSNrxs f/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/physics/mechanics/lagrange.pyz*LagrangesMethod.__init__..1fQi&()rr_Leom_m_cd_m_d_f_cd_f_d lam_coeffsr TypeError _forcelist isinstancer _bodiesinertiallam_vec_term1_term2_term3_term4_qqrr _t_qdots _qdoubledotsrconeqs _hol_coneqs) self Lagrangianqs forcelistbodiesframe hol_coneqs nonhol_coneqs mat_builds r__init__zLagrangesMethod.__init__isl<'*-./X H X H  (!*I  "JK K# E>:BC C  x h h h h |IJ J*ffkk."3"34  KK,,^->->?dff%: z* !-0 joon.?.?@  %rc  |j}tj|jd}t |j }|j j||_|jjtjj|_|j j|j j|_ |jr|j}t |}ttdt!|dzz|_|j| |_|j$j|j"z|_|jtj}|j|j|_|j+| |_nt/|d|_|j0ro|j2 t/|d|_t7|D]C\} t9t;|j0 }t= fd|D|j4|<Ent/|d|_|j|jz |j4z } | j|j|_| j+| |_ | |j&z |_!|jBS)zMethod to form Lagrange's equations of motion. Returns a vector of equations of motion using Lagrange's equations of the second kind. rzlam1:c3fK|](\}}|jj|*ywr)rdot).0vfNqds r z;LagrangesMethod.form_lagranges_equations..s*$Nfq!QVVB]%6%6q%9$Ns.1)"r2dictfromkeysr3lenr0rjacobianr+rr r1Tr,r4rstrr*r$r-r subsr"rr9r)r. enumerateziprsumr!r#r) r6qdsqdd_zeronr4m diffconeqsiflist without_lamrGrHs @@rform_lagranges_equationsz(LagrangesMethod.form_lagranges_equationsskk==!2!2A6 K gg&&s+ kk&&~'8'89;; gg&&tvv.00  ;;[[FF A!.3q1u:1E"FGDL%s33DO//++dll:DK^%6%67J#,,T->->?DJ$//(33DJ1+DK >> A1+DK"3 O2^DNNA>?!$$N$N!N A O 1+DKkkDKK/$++= (():):;  %%h// ,xxrc"|jSr)r\r6s r _form_eomszLagrangesMethod._form_eomss,,..rc|j td|jr/|jj |j j S|jS)a7Returns the mass matrix, which is augmented by the Lagrange multipliers, if necessary. Explanation =========== If the system is described by 'n' generalized coordinates and there are no constraint equations then an n X n matrix is returned. If there are 'n' generalized coordinates and 'm' constraint equations have been supplied during initialization then an n X (n+m) matrix is returned. The (n + m - 1)th and (n + m)th columns contain the coefficients of the Lagrange multipliers. -Need to compute the equations of motion first)r ValueErrorr4r!row_joinr$rNr^s r mass_matrixzLagrangesMethod.mass_matrixsJ" 88 LM M ;;II''(9(9: :99 rc|j tdt|j}t|j}t |j t|||z}t||j |j}|jr^t||j |jj t||}|j|j|S|j|S)z6Augments the coefficients of qdots to the mass_matrix.ra) rrbrLr0r4rrcrrdr col_join)r6rVrWrow1row2row3s rmass_matrix_fullz LagrangesMethod.mass_matrix_fulls 88 LM M K  1vuQA/Q{##D$4$45 ;;A;'' 3<|jj |j j |j S|jj |j S)z+Augments qdots to the forcing vector above.ra)rrbr4r2rfrlr"r^s r forcing_fullzLagrangesMethod.forcing_fullsb 88 LM M ;;;;'' 5>>tzzJ J;;'' 5 5rctj}|j}|j}|j |} |j } d} | |} | |} | |}| |}|j }|j}|j |}|}| }|j}|j|jz }|j }t| t|k7st|t|k7r-tdjt|t|tt!| | gt|k7r tdtt!||gt|k7r tdtt!||| | g}t#t%||}|j't(|D])}t |tj|vs tdt+||||||||||| | |||| |S)akReturns an instance of the Linearizer class, initiated from the data in the LagrangesMethod class. This may be more desirable than using the linearize class method, as the Linearizer object will allow more efficient recalculation (i.e. about varying operating points). Parameters ========== q_ind, qd_ind : array_like, optional The independent generalized coordinates and speeds. q_dep, qd_dep : array_like, optional The dependent generalized coordinates and speeds. 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. Returns ======= Linearizer An instantiated :class:`sympy.physics.mechanics.linearize.Linearizer`. c0|r t|StSrrrs rrz/LagrangesMethod.to_linearizer..Mrrz?Must supply {:} dependent coordinates, and {:} dependent speedszHMust partition q into q_ind and q_dep, with no extra or missing symbols.zKMust partition qd into qd_ind and qd_dep, with no extra or missing symbols.)keyzpCannot have derivatives of specified quantities when linearizing forcing terms. linear_solver)r r1r0r2rr*r5r4r+r,r.r-rLrbformatsetrlistr sortrr)r6q_indqd_indq_depqd_deprstr0uudlamsr>q_iq_du_iu_df_cf_vf_af_0f_1f_2f_3f_4insymsrrYs r to_linearizerzLagrangesMethod.to_linearizer$sD    FF KK VVAY||: kkhhqkbkk dkk)*{{l s8s3x 3s8s3x#7+,2F3s8SX,FH H vsCj! "c!f ,34 4 vsCj! "c!f ,89 9 VQ2t,-. $S&1 2 #$ NAA~(()Q. "MNN N #sCc3S!QsCD O Orc r|j|||||}|jdi|}||jfzS)awLinearize the equations of motion about a symbolic operating point. Parameters ========== 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. **kwargs Extra keyword arguments are passed to :meth:`sympy.physics.mechanics.linearize.Linearizer.linearize`. Explanation =========== If kwarg A_and_B is False (default), returns M, A, B, r for the linearized form, M*[q', u']^T = A*[q_ind, u_ind]^T + B*r. If kwarg A_and_B is True, returns A, B, r for the linearized form dx = A*x + B*r, where x = [q_ind, u_ind]^T. Note that this 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. Values may then be substituted in to these matrices, and the state space form found as A = P.T*M.inv()*A, B = P.T*M.inv()*B, where P = Linearizer.perm_mat. In both cases, r is found as all dynamicsymbols in the equations of motion that are not part of q, u, q', or u'. They are sorted in canonical form. The operating points may be also entered using the ``op_point`` kwarg. This takes a dictionary of {symbol: value}, or a an iterable of such dictionaries. The values may be numeric or symbolic. The more values you can specify beforehand, the faster this computation will run. For more documentation, please see the ``Linearizer`` class.rr)r linearizer) r6rxryrzr{rskwargs linearizerresults rrzLagrangesMethod.linearizewsLZ''vuf6C(E %%%//''rct|j}|dk(r tdt|tr|}n6t |ri}|D]}|j |n|i}n td|jj|jjt|| }|jj|j}t||}t||}|j!| | d}|dk(rt t#|j|S|dk(r t%|Stdj'|)aqSolves for the values of the lagrange multipliers symbolically at the specified operating point. Parameters ========== op_point : dict or iterable of dicts, optional Point at which to solve at. The operating point is specified as a dictionary or iterable of dictionaries of {symbol: value}. The value may be numeric or symbolic itself. sol_type : str, optional Solution return type. Valid options are: - 'dict': A dict of {symbol : value} (default) - 'Matrix': An ordered column matrix of the solution rz0System has no lagrange multipliers to solve for.NzDop_point must be either a dictionary or an iterable of dictionaries.rJrzUnknown sol_type {:}.)rLr*rbr'rJrupdater%rdrfr$rcrrlr"r LUsolverRrrt) r6op_pointsol_typek op_point_dictoprd force_matrixsol_lists rsolve_multipliersz!LagrangesMethod.solve_multiplierssE&   6OP P h %$M h M )$$R( )  M89 9&&//1I1Ia 21 ||,,TZZ8 K7 \=9 && }5qbc: v DLL(34 4  !(# #4;;HEF Frc |6|jj|j|_|jS|jj |d|jz|_|jS)a/Returns equations that can be solved numerically. Parameters ========== inv_method : str The specific sympy inverse matrix calculation method to use. For a list of valid methods, see :meth:`~sympy.matrices.matrixbase.MatrixBase.inv` T)try_block_diag)rjrrn_rhsinv)r6 inv_methodrs rrhszLagrangesMethod.rhssq  --55d6G6GHDIyy..22:(,3.040A0ABDIyyrc|jSr)r/r^s rr0zLagrangesMethod.qs wwrc|jSr)r2r^s rr}zLagrangesMethod.us {{rc|jSr)r(r^s rr:zLagrangesMethod.bodiess ||rc|jSrr&r^s rr9zLagrangesMethod.forcelist rc|jSrrr^s rloadszLagrangesMethod.loadsrr)NNNNN)NNNNLU)NrJr)__name__ __module__ __qualname____doc__r?r\r_propertyrdrjrlrnrrrrr0r}r:r9rrrrrr sYvKO04C&J6p/. ' '66IM$(QOfEI $0(d0Gd&rN)sympyrrrrrsympy.core.sortingrsympy.physics.vectorr r sympy.physics.mechanics.methodr !sympy.physics.mechanics.functionsr r rr!sympy.physics.mechanics.linearizersympy.utilities.iterablesr__all__rrrrrs<33/?3GG8.  shsr