K i\dZddlmZddlmZddlmZmZddlm Z m Z ddl m Z m Z ddlmZmZddlmZdd lmZgd ZGd d eZGd deZGddeZGddeZGddeZGddeZGddeZGddeZedGddZy) zBImplementations of characteristic curves for musculotendon models.) dataclass)UnevaluatedExpr)ArgumentIndexErrorFunction)FloatInteger)explog)coshsinh)sqrt) PRECEDENCE) CharacteristicCurveCollectionCharacteristicCurveFunction"FiberForceLengthActiveDeGroote2016#FiberForceLengthPassiveDeGroote2016*FiberForceLengthPassiveInverseDeGroote2016FiberForceVelocityDeGroote2016%FiberForceVelocityInverseDeGroote2016TendonForceLengthDeGroote2016$TendonForceLengthInverseDeGroote2016cReZdZdZedZdZeZeZeZ eZ eZ eZ eZ eZeZeZeZy)rz@Base class for all musculotendon characteristic curve functions.c8d|jd}t|)NzCannot directly instantiate zD, instances of characteristic curves must be of a concrete subclass.)__name__ TypeError)clsmsgs f/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/physics/biomechanics/curve.pyevalz CharacteristicCurveFunction.evals-+3<<*:;D E nct|j|j|jddtdS)a8Print code for the function defining the curve using a printer. Explanation =========== The order of operations may need to be controlled as constant folding the numeric terms within the equations of a musculotendon characteristic curve can sometimes results in a numerically-unstable expression. Parameters ========== printer : Printer The printer to be used to print a string representation of the characteristic curve as valid code in the target language. FdeepevaluateAtom)_print parenthesizedoitr)selfprinters r _print_codez'CharacteristicCurveFunction._print_code's9&~~g22 II55I 1:f3E   r N)r __module__ __qualname____doc__ classmethodrr+_ccode _cupycode_cxxcode_fcode_jaxcode _lambdacode _mpmathcode_octave _pythoncode _numpycode _scipycoder rrrsUJ .FIH FHKKGKJJr rcTeZdZdZedZedZdZd dZd dZ d dZ dZ y ) ra{ Tendon force-length curve based on De Groote et al., 2016 [1]_. Explanation =========== Gives the normalized tendon force produced as a function of normalized tendon length. The function is defined by the equation: $fl^T = c_0 \exp{c_3 \left( \tilde{l}^T - c_1 \right)} - c_2$ with constant values of $c_0 = 0.2$, $c_1 = 0.995$, $c_2 = 0.25$, and $c_3 = 33.93669377311689$. While it is possible to change the constant values, these were carefully selected in the original publication to give the characteristic curve specific and required properties. For example, the function produces no force when the tendon is in an unstrained state. It also produces a force of 1 normalized unit when the tendon is under a 5% strain. Examples ======== The preferred way to instantiate :class:`TendonForceLengthDeGroote2016` is using the :meth:`~.with_defaults` constructor because this will automatically populate the constants within the characteristic curve equation with the floating point values from the original publication. This constructor takes a single argument corresponding to normalized tendon length. We'll create a :class:`~.Symbol` called ``l_T_tilde`` to represent this. >>> from sympy import Symbol >>> from sympy.physics.biomechanics import TendonForceLengthDeGroote2016 >>> l_T_tilde = Symbol('l_T_tilde') >>> fl_T = TendonForceLengthDeGroote2016.with_defaults(l_T_tilde) >>> fl_T TendonForceLengthDeGroote2016(l_T_tilde, 0.2, 0.995, 0.25, 33.93669377311689) It's also possible to populate the four constants with your own values too. >>> from sympy import symbols >>> c0, c1, c2, c3 = symbols('c0 c1 c2 c3') >>> fl_T = TendonForceLengthDeGroote2016(l_T_tilde, c0, c1, c2, c3) >>> fl_T TendonForceLengthDeGroote2016(l_T_tilde, c0, c1, c2, c3) You don't just have to use symbols as the arguments, it's also possible to use expressions. Let's create a new pair of symbols, ``l_T`` and ``l_T_slack``, representing tendon length and tendon slack length respectively. We can then represent ``l_T_tilde`` as an expression, the ratio of these. >>> l_T, l_T_slack = symbols('l_T l_T_slack') >>> l_T_tilde = l_T/l_T_slack >>> fl_T = TendonForceLengthDeGroote2016.with_defaults(l_T_tilde) >>> fl_T TendonForceLengthDeGroote2016(l_T/l_T_slack, 0.2, 0.995, 0.25, 33.93669377311689) To inspect the actual symbolic expression that this function represents, we can call the :meth:`~.doit` method on an instance. We'll use the keyword argument ``evaluate=False`` as this will keep the expression in its canonical form and won't simplify any constants. >>> fl_T.doit(evaluate=False) -0.25 + 0.2*exp(33.93669377311689*(l_T/l_T_slack - 0.995)) The function can also be differentiated. We'll differentiate with respect to l_T using the ``diff`` method on an instance with the single positional argument ``l_T``. >>> fl_T.diff(l_T) 6.787338754623378*exp(33.93669377311689*(l_T/l_T_slack - 0.995))/l_T_slack References ========== .. [1] De Groote, F., Kinney, A. L., Rao, A. V., & Fregly, B. J., Evaluation of direct collocation optimal control problem formulations for solving the muscle redundancy problem, Annals of biomedical engineering, 44(10), (2016) pp. 2922-2936 crtd}td}td}td}||||||S)aRecommended constructor that will use the published constants. Explanation =========== Returns a new instance of the tendon force-length function using the four constant values specified in the original publication. These have the values: $c_0 = 0.2$ $c_1 = 0.995$ $c_2 = 0.25$ $c_3 = 33.93669377311689$ Parameters ========== l_T_tilde : Any (sympifiable) Normalized tendon length. 0.20.9950.2533.93669377311689rr l_T_tildec0c1c2c3s r with_defaultsz+TendonForceLengthDeGroote2016.with_defaultss=05\ 7^ 6] & '9b"b"--r cy)aEvaluation of basic inputs. Parameters ========== l_T_tilde : Any (sympifiable) Normalized tendon length. c0 : Any (sympifiable) The first constant in the characteristic equation. The published value is ``0.2``. c1 : Any (sympifiable) The second constant in the characteristic equation. The published value is ``0.995``. c2 : Any (sympifiable) The third constant in the characteristic equation. The published value is ``0.25``. c3 : Any (sympifiable) The fourth constant in the characteristic equation. The published value is ``33.93669377311689``. Nr;rCs rrz"TendonForceLengthDeGroote2016.eval. r cF|jddj|Sz4Evaluate the expression numerically using ``evalf``.Fr"r( _eval_evalfr)precs rrOz)TendonForceLengthDeGroote2016._eval_evalf yyeey4@@FFr c .|j^}}|rA||d<|jdd|i|}|Dcgc]}|jdd|i|c}\}}} } n|\}}} } |r|t| ||z zz| z S|t| t||z zz| z Scc}wEvaluate the expression defining the function. Parameters ========== deep : bool Whether ``doit`` should be recursively called. Default is ``True``. evaluate : bool. Whether the SymPy expression should be evaluated as it is constructed. If ``False``, then no constant folding will be conducted which will leave the expression in a more numerically- stable for values of ``l_T_tilde`` that correspond to a sensible operating range for a musculotendon. Default is ``True``. **kwargs : dict[str, Any] Additional keyword argument pairs to be recursively passed to ``doit``. r$r#r;argsr(r r) r)r#r$hintsrD constantscrErFrGrHs rr(z"TendonForceLengthDeGroote2016.doits&!%  I  (E* & :D:E:IBKLQfaff8$8%8LNBB&NBB c"i"n-..3 3#bR8899B>>MBc|j\}}}}}|dk(r ||zt|t||z zzS|dk(rt|t||z zS|dk(r!| |zt|t||z zzS|dk(r tdS|dk(r#|||z zt|t||z zzSt ||9Derivative of the function with respect to a single argument. Parameters ========== argindex : int The index of the function's arguments with respect to which the derivative should be taken. Argument indexes start at ``1``. Default is ``1``. )rWr rrr)r)argindexrDrErFrGrHs rfdiffz#TendonForceLengthDeGroote2016.fdiffs%)II! 2r2r q=b5R B ??@@ @ ]r/)b.99: : ]3r6#bR!@@AA A ]2;  ]y2~&s2oi"n.M+M'NN N x00r ctSzInverse function. Parameters ========== argindex : int Value to start indexing the arguments at. Default is ``1``. )rr)res rinversez%TendonForceLengthDeGroote2016.inverses 43r cL|jd}|j|}d|zS)Print a LaTeX representation of the function defining the curve. Parameters ========== printer : Printer The printer to be used to print the LaTeX string representation. rz%\operatorname{fl}^T \left( %s \right)rWr&)r)r*rD _l_T_tildes r_latexz$TendonForceLengthDeGroote2016._latex"*IIaL ^^I. 7*DDr NTTr_ rr,r-r.r/rIrrOr(rfrjror;r rrrKsMSj..:  0G?@14 4 Er rcTeZdZdZedZedZdZd dZd dZ d dZ dZ y ) ra Inverse tendon force-length curve based on De Groote et al., 2016 [1]_. Explanation =========== Gives the normalized tendon length that produces a specific normalized tendon force. The function is defined by the equation: ${fl^T}^{-1} = frac{\log{\frac{fl^T + c_2}{c_0}}}{c_3} + c_1$ with constant values of $c_0 = 0.2$, $c_1 = 0.995$, $c_2 = 0.25$, and $c_3 = 33.93669377311689$. This function is the exact analytical inverse of the related tendon force-length curve ``TendonForceLengthDeGroote2016``. While it is possible to change the constant values, these were carefully selected in the original publication to give the characteristic curve specific and required properties. For example, the function produces no force when the tendon is in an unstrained state. It also produces a force of 1 normalized unit when the tendon is under a 5% strain. Examples ======== The preferred way to instantiate :class:`TendonForceLengthInverseDeGroote2016` is using the :meth:`~.with_defaults` constructor because this will automatically populate the constants within the characteristic curve equation with the floating point values from the original publication. This constructor takes a single argument corresponding to normalized tendon force-length, which is equal to the tendon force. We'll create a :class:`~.Symbol` called ``fl_T`` to represent this. >>> from sympy import Symbol >>> from sympy.physics.biomechanics import TendonForceLengthInverseDeGroote2016 >>> fl_T = Symbol('fl_T') >>> l_T_tilde = TendonForceLengthInverseDeGroote2016.with_defaults(fl_T) >>> l_T_tilde TendonForceLengthInverseDeGroote2016(fl_T, 0.2, 0.995, 0.25, 33.93669377311689) It's also possible to populate the four constants with your own values too. >>> from sympy import symbols >>> c0, c1, c2, c3 = symbols('c0 c1 c2 c3') >>> l_T_tilde = TendonForceLengthInverseDeGroote2016(fl_T, c0, c1, c2, c3) >>> l_T_tilde TendonForceLengthInverseDeGroote2016(fl_T, c0, c1, c2, c3) To inspect the actual symbolic expression that this function represents, we can call the :meth:`~.doit` method on an instance. We'll use the keyword argument ``evaluate=False`` as this will keep the expression in its canonical form and won't simplify any constants. >>> l_T_tilde.doit(evaluate=False) c1 + log((c2 + fl_T)/c0)/c3 The function can also be differentiated. We'll differentiate with respect to l_T using the ``diff`` method on an instance with the single positional argument ``l_T``. >>> l_T_tilde.diff(fl_T) 1/(c3*(c2 + fl_T)) References ========== .. [1] De Groote, F., Kinney, A. L., Rao, A. V., & Fregly, B. J., Evaluation of direct collocation optimal control problem formulations for solving the muscle redundancy problem, Annals of biomedical engineering, 44(10), (2016) pp. 2922-2936 crtd}td}td}td}||||||S)aRecommended constructor that will use the published constants. Explanation =========== Returns a new instance of the inverse tendon force-length function using the four constant values specified in the original publication. These have the values: $c_0 = 0.2$ $c_1 = 0.995$ $c_2 = 0.25$ $c_3 = 33.93669377311689$ Parameters ========== fl_T : Any (sympifiable) Normalized tendon force as a function of tendon length. r>r?r@rArBrfl_TrErFrGrHs rrIz2TendonForceLengthInverseDeGroote2016.with_defaults|s=05\ 7^ 6] & '4RR((r cy)aEvaluation of basic inputs. Parameters ========== fl_T : Any (sympifiable) Normalized tendon force as a function of tendon length. c0 : Any (sympifiable) The first constant in the characteristic equation. The published value is ``0.2``. c1 : Any (sympifiable) The second constant in the characteristic equation. The published value is ``0.995``. c2 : Any (sympifiable) The third constant in the characteristic equation. The published value is ``0.25``. c3 : Any (sympifiable) The fourth constant in the characteristic equation. The published value is ``33.93669377311689``. Nr;rvs rrz)TendonForceLengthInverseDeGroote2016.evalrKr cF|jddj|SrMrNrPs rrOz0TendonForceLengthInverseDeGroote2016._eval_evalfrRr c .|j^}}|rA||d<|jdd|i|}|Dcgc]}|jdd|i|c}\}}} } n|\}}} } |rt|| z|z | z |zStt|| z|z | z |zScc}wrT)rWr(r r) r)r#r$rXrwrYrZrErFrGrHs rr(z)TendonForceLengthInverseDeGroote2016.doits& 99y  (E* 4990$0%0DBKLQfaff8$8%8LNBB&NBB r 2~&r)B. .?D2Ir>23B6;;Mr[c|j\}}}}}|dk(r d|||zzz S|dk(rd||zz S|dk(r tdS|dk(r d|||zzz S|dk(r!tt||z|z  |dzz St ||)r^r_r`rcrarbrd)rWrr rr)r)rerwrErFrGrHs rrfz*TendonForceLengthInverseDeGroote2016.fdiffs $yyb"b" q=b$)n% % ]r"u:  ]1:  ]b$)n% % ]B788Q> > x00r ctSrh)rris rrjz,TendonForceLengthInverseDeGroote2016.inverses -,r cL|jd}|j|}d|zS)rlrz9\left( \operatorname{fl}^T \right)^{-1} \left( %s \right)rm)r)r*rw_fl_Ts rroz+TendonForceLengthInverseDeGroote2016._latex*yy|t$KeSSr Nrqrrrsr;r rrr1sMHT)):  0G<@14 - Tr rcTeZdZdZedZedZdZd dZd dZ d dZ dZ y ) ra Passive muscle fiber force-length curve based on De Groote et al., 2016 [1]_. Explanation =========== The function is defined by the equation: $fl^M_{pas} = \frac{\frac{\exp{c_1 \left(\tilde{l^M} - 1\right)}}{c_0} - 1}{\exp{c_1} - 1}$ with constant values of $c_0 = 0.6$ and $c_1 = 4.0$. While it is possible to change the constant values, these were carefully selected in the original publication to give the characteristic curve specific and required properties. For example, the function produces a passive fiber force very close to 0 for all normalized fiber lengths between 0 and 1. Examples ======== The preferred way to instantiate :class:`FiberForceLengthPassiveDeGroote2016` is using the :meth:`~.with_defaults` constructor because this will automatically populate the constants within the characteristic curve equation with the floating point values from the original publication. This constructor takes a single argument corresponding to normalized muscle fiber length. We'll create a :class:`~.Symbol` called ``l_M_tilde`` to represent this. >>> from sympy import Symbol >>> from sympy.physics.biomechanics import FiberForceLengthPassiveDeGroote2016 >>> l_M_tilde = Symbol('l_M_tilde') >>> fl_M = FiberForceLengthPassiveDeGroote2016.with_defaults(l_M_tilde) >>> fl_M FiberForceLengthPassiveDeGroote2016(l_M_tilde, 0.6, 4.0) It's also possible to populate the two constants with your own values too. >>> from sympy import symbols >>> c0, c1 = symbols('c0 c1') >>> fl_M = FiberForceLengthPassiveDeGroote2016(l_M_tilde, c0, c1) >>> fl_M FiberForceLengthPassiveDeGroote2016(l_M_tilde, c0, c1) You don't just have to use symbols as the arguments, it's also possible to use expressions. Let's create a new pair of symbols, ``l_M`` and ``l_M_opt``, representing muscle fiber length and optimal muscle fiber length respectively. We can then represent ``l_M_tilde`` as an expression, the ratio of these. >>> l_M, l_M_opt = symbols('l_M l_M_opt') >>> l_M_tilde = l_M/l_M_opt >>> fl_M = FiberForceLengthPassiveDeGroote2016.with_defaults(l_M_tilde) >>> fl_M FiberForceLengthPassiveDeGroote2016(l_M/l_M_opt, 0.6, 4.0) To inspect the actual symbolic expression that this function represents, we can call the :meth:`~.doit` method on an instance. We'll use the keyword argument ``evaluate=False`` as this will keep the expression in its canonical form and won't simplify any constants. >>> fl_M.doit(evaluate=False) 0.0186573603637741*(-1 + exp(6.66666666666667*(l_M/l_M_opt - 1))) The function can also be differentiated. We'll differentiate with respect to l_M using the ``diff`` method on an instance with the single positional argument ``l_M``. >>> fl_M.diff(l_M) 0.12438240242516*exp(6.66666666666667*(l_M/l_M_opt - 1))/l_M_opt References ========== .. [1] De Groote, F., Kinney, A. L., Rao, A. V., & Fregly, B. J., Evaluation of direct collocation optimal control problem formulations for solving the muscle redundancy problem, Annals of biomedical engineering, 44(10), (2016) pp. 2922-2936 cBtd}td}||||S)aRecommended constructor that will use the published constants. Explanation =========== Returns a new instance of the muscle fiber passive force-length function using the four constant values specified in the original publication. These have the values: $c_0 = 0.6$ $c_1 = 4.0$ Parameters ========== l_M_tilde : Any (sympifiable) Normalized muscle fiber length. 0.64.0rBr l_M_tilderErFs rrIz1FiberForceLengthPassiveDeGroote2016.with_defaults]s%.5\ 5\9b"%%r cy)aEvaluation of basic inputs. Parameters ========== l_M_tilde : Any (sympifiable) Normalized muscle fiber length. c0 : Any (sympifiable) The first constant in the characteristic equation. The published value is ``0.6``. c1 : Any (sympifiable) The second constant in the characteristic equation. The published value is ``4.0``. Nr;rs rrz(FiberForceLengthPassiveDeGroote2016.evalx" r cF|jddj|SrMrNrPs rrOz/FiberForceLengthPassiveDeGroote2016._eval_evalfrRr c b|j^}}|r?||d<|jdd|i|}|Dcgc]}|jdd|i|c}\}}n|\}}|r&t||dz z|z dz t|dz z St|t|dz z|z dz t|dz z Scc}wrUr$r#r_r;rV) r)r#r$rXrrYrZrErFs rr(z(FiberForceLengthPassiveDeGroote2016.doits&!%  I  (E* & :D:E:I:CDQfaff0$0%0DFBFB Y]+R/014s2w{C CR A 66:;a?#b'A+NNEB,c 0|j\}}}|dk(r2|t|t|dz z|z z|t|dz zz S|dk(rE| t|t|dz z|z zt|dz z|dzt|dz zz S|dk(rut| dt|t|dz z|z zzt|dz dzz t|t|dz z|z |dz z|t|dz zz zSt||)r^r_r`rarc)rWr rr)r)rerrErFs rrfz)FiberForceLengthPassiveDeGroote2016.fdiffsF!II 2r q=c"_Y];;B>??SWq[AQR R ]C?9q=99"<== Q/013QB! 1DF ]R"s2oi!m&D#DR#GHHI3r7UV;YZJZZbQ77:;Y]KRQTUWQX[\Q\M]^_  !x00r ctSrh)rris rrjz+FiberForceLengthPassiveDeGroote2016.inverses :9r cL|jd}|j|}d|zS)rlrz+\operatorname{fl}^M_{pas} \left( %s \right)rmr)r*r _l_M_tildes rroz*FiberForceLengthPassiveDeGroote2016._latex*IIaL ^^I. = JJr Nrqrrrsr;r rrr sNN`&&4  $GO@18 : Kr rcTeZdZdZedZedZdZd dZd dZ d dZ dZ y ) ra Inverse passive muscle fiber force-length curve based on De Groote et al., 2016 [1]_. Explanation =========== Gives the normalized muscle fiber length that produces a specific normalized passive muscle fiber force. The function is defined by the equation: ${fl^M_{pas}}^{-1} = \frac{c_0 \log{\left(\exp{c_1} - 1\right)fl^M_pas + 1}}{c_1} + 1$ with constant values of $c_0 = 0.6$ and $c_1 = 4.0$. This function is the exact analytical inverse of the related tendon force-length curve ``FiberForceLengthPassiveDeGroote2016``. While it is possible to change the constant values, these were carefully selected in the original publication to give the characteristic curve specific and required properties. For example, the function produces a passive fiber force very close to 0 for all normalized fiber lengths between 0 and 1. Examples ======== The preferred way to instantiate :class:`FiberForceLengthPassiveInverseDeGroote2016` is using the :meth:`~.with_defaults` constructor because this will automatically populate the constants within the characteristic curve equation with the floating point values from the original publication. This constructor takes a single argument corresponding to the normalized passive muscle fiber length-force component of the muscle fiber force. We'll create a :class:`~.Symbol` called ``fl_M_pas`` to represent this. >>> from sympy import Symbol >>> from sympy.physics.biomechanics import FiberForceLengthPassiveInverseDeGroote2016 >>> fl_M_pas = Symbol('fl_M_pas') >>> l_M_tilde = FiberForceLengthPassiveInverseDeGroote2016.with_defaults(fl_M_pas) >>> l_M_tilde FiberForceLengthPassiveInverseDeGroote2016(fl_M_pas, 0.6, 4.0) It's also possible to populate the two constants with your own values too. >>> from sympy import symbols >>> c0, c1 = symbols('c0 c1') >>> l_M_tilde = FiberForceLengthPassiveInverseDeGroote2016(fl_M_pas, c0, c1) >>> l_M_tilde FiberForceLengthPassiveInverseDeGroote2016(fl_M_pas, c0, c1) To inspect the actual symbolic expression that this function represents, we can call the :meth:`~.doit` method on an instance. We'll use the keyword argument ``evaluate=False`` as this will keep the expression in its canonical form and won't simplify any constants. >>> l_M_tilde.doit(evaluate=False) c0*log(1 + fl_M_pas*(exp(c1) - 1))/c1 + 1 The function can also be differentiated. We'll differentiate with respect to fl_M_pas using the ``diff`` method on an instance with the single positional argument ``fl_M_pas``. >>> l_M_tilde.diff(fl_M_pas) c0*(exp(c1) - 1)/(c1*(fl_M_pas*(exp(c1) - 1) + 1)) References ========== .. [1] De Groote, F., Kinney, A. L., Rao, A. V., & Fregly, B. J., Evaluation of direct collocation optimal control problem formulations for solving the muscle redundancy problem, Annals of biomedical engineering, 44(10), (2016) pp. 2922-2936 cBtd}td}||||S)aRecommended constructor that will use the published constants. Explanation =========== Returns a new instance of the inverse muscle fiber passive force-length function using the four constant values specified in the original publication. These have the values: $c_0 = 0.6$ $c_1 = 4.0$ Parameters ========== fl_M_pas : Any (sympifiable) Normalized passive muscle fiber force as a function of muscle fiber length. rrrBrfl_M_pasrErFs rrIz8FiberForceLengthPassiveInverseDeGroote2016.with_defaults2s%05\ 5\8R$$r cy)aEvaluation of basic inputs. Parameters ========== fl_M_pas : Any (sympifiable) Normalized passive muscle fiber force. c0 : Any (sympifiable) The first constant in the characteristic equation. The published value is ``0.6``. c1 : Any (sympifiable) The second constant in the characteristic equation. The published value is ``4.0``. Nr;rs rrz/FiberForceLengthPassiveInverseDeGroote2016.evalNrr cF|jddj|SrMrNrPs rrOz6FiberForceLengthPassiveInverseDeGroote2016._eval_evalfarRr c b|j^}}|r?||d<|jdd|i|}|Dcgc]}|jdd|i|c}\}}n|\}}|r&|t|t|dz zdzz|z dzS|tt |t|dz zdzz|z dzScc}wr)rWr(r r r) r)r#r$rXrrYrZrErFs rr(z/FiberForceLengthPassiveInverseDeGroote2016.doites& $yy9  (E* $x}}8$8%8H:CDQfaff0$0%0DFBFB c(CGaK01455b81< <#ohB! &<=ABB2EIIErc|j\}}}|dk(r)|t|dz z||t|dz zdzzz S|dk(r t|t|dz zdz|z S|dk(rP||zt|z||t|dz zdzzz |t|t|dz zdzz|dzz z St||)r^r_r`ra)rWr r r)r)rerrErFs rrfz0FiberForceLengthPassiveInverseDeGroote2016.fdiffs 99"b q=s2w{#R3r7Q;)?!)C%DE E ]xR1-1225 5 ]8 CG#R3r7Q;)?!)C%DES3r7Q;/!344RU:;  !x00r ctSrh)rris rrjz2FiberForceLengthPassiveInverseDeGroote2016.inverses 32r cL|jd}|j|}d|zS)rlrz?\left( \operatorname{fl}^M_{pas} \right)^{-1} \left( %s \right)rm)r)r*r _fl_M_pass rroz1FiberForceLengthPassiveInverseDeGroote2016._latexs+99Q<NN8, QT]]]r Nrqrrrsr;r rrrsNIV%%6  $GJ@12 3 ^r rcLeZdZdZedZedZdZd dZd dZ dZ y) raActive muscle fiber force-length curve based on De Groote et al., 2016 [1]_. Explanation =========== The function is defined by the equation: $fl_{\text{act}}^M = c_0 \exp\left(-\frac{1}{2}\left(\frac{\tilde{l}^M - c_1}{c_2 + c_3 \tilde{l}^M}\right)^2\right) + c_4 \exp\left(-\frac{1}{2}\left(\frac{\tilde{l}^M - c_5}{c_6 + c_7 \tilde{l}^M}\right)^2\right) + c_8 \exp\left(-\frac{1}{2}\left(\frac{\tilde{l}^M - c_9}{c_{10} + c_{11} \tilde{l}^M}\right)^2\right)$ with constant values of $c0 = 0.814$, $c1 = 1.06$, $c2 = 0.162$, $c3 = 0.0633$, $c4 = 0.433$, $c5 = 0.717$, $c6 = -0.0299$, $c7 = 0.2$, $c8 = 0.1$, $c9 = 1.0$, $c10 = 0.354$, and $c11 = 0.0$. While it is possible to change the constant values, these were carefully selected in the original publication to give the characteristic curve specific and required properties. For example, the function produces a active fiber force of 1 at a normalized fiber length of 1, and an active fiber force of 0 at normalized fiber lengths of 0 and 2. Examples ======== The preferred way to instantiate :class:`FiberForceLengthActiveDeGroote2016` is using the :meth:`~.with_defaults` constructor because this will automatically populate the constants within the characteristic curve equation with the floating point values from the original publication. This constructor takes a single argument corresponding to normalized muscle fiber length. We'll create a :class:`~.Symbol` called ``l_M_tilde`` to represent this. >>> from sympy import Symbol >>> from sympy.physics.biomechanics import FiberForceLengthActiveDeGroote2016 >>> l_M_tilde = Symbol('l_M_tilde') >>> fl_M = FiberForceLengthActiveDeGroote2016.with_defaults(l_M_tilde) >>> fl_M FiberForceLengthActiveDeGroote2016(l_M_tilde, 0.814, 1.06, 0.162, 0.0633, 0.433, 0.717, -0.0299, 0.2, 0.1, 1.0, 0.354, 0.0) It's also possible to populate the two constants with your own values too. >>> from sympy import symbols >>> c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11 = symbols('c0:12') >>> fl_M = FiberForceLengthActiveDeGroote2016(l_M_tilde, c0, c1, c2, c3, ... c4, c5, c6, c7, c8, c9, c10, c11) >>> fl_M FiberForceLengthActiveDeGroote2016(l_M_tilde, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11) You don't just have to use symbols as the arguments, it's also possible to use expressions. Let's create a new pair of symbols, ``l_M`` and ``l_M_opt``, representing muscle fiber length and optimal muscle fiber length respectively. We can then represent ``l_M_tilde`` as an expression, the ratio of these. >>> l_M, l_M_opt = symbols('l_M l_M_opt') >>> l_M_tilde = l_M/l_M_opt >>> fl_M = FiberForceLengthActiveDeGroote2016.with_defaults(l_M_tilde) >>> fl_M FiberForceLengthActiveDeGroote2016(l_M/l_M_opt, 0.814, 1.06, 0.162, 0.0633, 0.433, 0.717, -0.0299, 0.2, 0.1, 1.0, 0.354, 0.0) To inspect the actual symbolic expression that this function represents, we can call the :meth:`~.doit` method on an instance. We'll use the keyword argument ``evaluate=False`` as this will keep the expression in its canonical form and won't simplify any constants. >>> fl_M.doit(evaluate=False) 0.814*exp(-(l_M/l_M_opt - 1.06)**2/(2*(0.0633*l_M/l_M_opt + 0.162)**2)) + 0.433*exp(-(l_M/l_M_opt - 0.717)**2/(2*(0.2*l_M/l_M_opt - 0.0299)**2)) + 0.1*exp(-3.98991349867535*(l_M/l_M_opt - 1.0)**2) The function can also be differentiated. We'll differentiate with respect to l_M using the ``diff`` method on an instance with the single positional argument ``l_M``. >>> fl_M.diff(l_M) ((-0.79798269973507*l_M/l_M_opt + 0.79798269973507)*exp(-3.98991349867535*(l_M/l_M_opt - 1.0)**2) + (0.433*(-l_M/l_M_opt + 0.717)/(0.2*l_M/l_M_opt - 0.0299)**2 + 0.0866*(l_M/l_M_opt - 0.717)**2/(0.2*l_M/l_M_opt - 0.0299)**3)*exp(-(l_M/l_M_opt - 0.717)**2/(2*(0.2*l_M/l_M_opt - 0.0299)**2)) + (0.814*(-l_M/l_M_opt + 1.06)/(0.0633*l_M/l_M_opt + 0.162)**2 + 0.0515262*(l_M/l_M_opt - 1.06)**2/(0.0633*l_M/l_M_opt + 0.162)**3)*exp(-(l_M/l_M_opt - 1.06)**2/(2*(0.0633*l_M/l_M_opt + 0.162)**2)))/l_M_opt References ========== .. [1] De Groote, F., Kinney, A. L., Rao, A. V., & Fregly, B. J., Evaluation of direct collocation optimal control problem formulations for solving the muscle redundancy problem, Annals of biomedical engineering, 44(10), (2016) pp. 2922-2936 c2td}td}td}td}td}td}td}td} td } td } td } td } |||||||||| | | | | S) aRecommended constructor that will use the published constants. Explanation =========== Returns a new instance of the inverse muscle fiber act force-length function using the four constant values specified in the original publication. These have the values: $c0 = 0.814$ $c1 = 1.06$ $c2 = 0.162$ $c3 = 0.0633$ $c4 = 0.433$ $c5 = 0.717$ $c6 = -0.0299$ $c7 = 0.2$ $c8 = 0.1$ $c9 = 1.0$ $c10 = 0.354$ $c11 = 0.0$ Parameters ========== fl_M_act : Any (sympifiable) Normalized passive muscle fiber force as a function of muscle fiber length. z0.814z1.06z0.162z0.0633z0.433z0.717z-0.0299r>z0.1z1.0z0.354z0.0rBrrrErFrGrHc4c5c6c7c8c9c10c11s rrIz0FiberForceLengthActiveDeGroote2016.with_defaultssD7^ 6] 7^ 8_ 7^ 7^ 9  5\ 5\ 5\GnEl9b"b"b"b"b"c3OOr cy)a5Evaluation of basic inputs. Parameters ========== l_M_tilde : Any (sympifiable) Normalized muscle fiber length. c0 : Any (sympifiable) The first constant in the characteristic equation. The published value is ``0.814``. c1 : Any (sympifiable) The second constant in the characteristic equation. The published value is ``1.06``. c2 : Any (sympifiable) The third constant in the characteristic equation. The published value is ``0.162``. c3 : Any (sympifiable) The fourth constant in the characteristic equation. The published value is ``0.0633``. c4 : Any (sympifiable) The fifth constant in the characteristic equation. The published value is ``0.433``. c5 : Any (sympifiable) The sixth constant in the characteristic equation. The published value is ``0.717``. c6 : Any (sympifiable) The seventh constant in the characteristic equation. The published value is ``-0.0299``. c7 : Any (sympifiable) The eighth constant in the characteristic equation. The published value is ``0.2``. c8 : Any (sympifiable) The ninth constant in the characteristic equation. The published value is ``0.1``. c9 : Any (sympifiable) The tenth constant in the characteristic equation. The published value is ``1.0``. c10 : Any (sympifiable) The eleventh constant in the characteristic equation. The published value is ``0.354``. c11 : Any (sympifiable) The tweflth constant in the characteristic equation. The published value is ``0.0``. Nr;rs rrz'FiberForceLengthActiveDeGroote2016.evalNs^ r cF|jddj|SrMrNrPs rrOz.FiberForceLengthActiveDeGroote2016._eval_evalfrRr c |j^}}|r:||d<|jdd|i|}|Dcgc]}|jdd|i|}}|\ }}} } } } } }}}}}|re|t||z | | |zzz dz dz z| t|| z | ||zzz dz dz zz|t||z |||zzz dz dz zzS|tt||z | | |zzz dz dz z| tt|| z | ||zzz dz dz zz|tt||z |||zzz dz dz zzScc}w)aEvaluate the expression defining the function. Parameters ========== deep : bool Whether ``doit`` should be recursively called. Default is ``True``. evaluate : bool. Whether the SymPy expression should be evaluated as it is constructed. If ``False``, then no constant folding will be conducted which will leave the expression in a more numerically- stable for values of ``l_M_tilde`` that correspond to a sensible operating range for a musculotendon. Default is ``True``. **kwargs : dict[str, Any] Additional keyword argument pairs to be recursively passed to ``doit``. r$r#r`r;rV)r)r#r$rXrrYrZrErFrGrHrrrrrrrrs rr(z'FiberForceLengthActiveDeGroote2016.doits&!%  I  (E* & :D:E:I=FG3T3U3GIG;D8BBBBBS 39r>BI,=>BCAEFFSY^b2i<.?@1DEaGHHISY^cC M.ABQFGIJJK  soi"n5rByL7HIAMNqPQ Q B7bl9JKaOPQRRSS T B7s9}9LMPQQRSTTUU V HsEc p|j\ }}}}}}}} } } } } }|dk(r||||z dzz|||zzdzz ||z |||zzdzz zzt||z dz d|||zzdzzz z|| ||z dzz| | |zzdzz ||z | | |zzdzz zzt||z dz d| | |zzdzzz zz| ||| z dzz| ||zzdzz | |z | ||zzdzz zzt|| z dz d| ||zzdzzz zzS|dk(r!t||z dz d|||zzdzzz S|dk(r6|||z z|||zzdzz t||z dz d|||zzdzzz zS|dk(r9|||z dzz|||zzdzz t||z dz d|||zzdzzz zS|dk(r<||z||z dzz|||zzdzz t||z dz d|||zzdzzz zS|dk(r!t||z dz d| | |zzdzzz S|dk(r6|||z z| | |zzdzz t||z dz d| | |zzdzzz zS|dk(r9|||z dzz| | |zzdzz t||z dz d| | |zzdzzz zS|d k(r<||z||z dzz| | |zzdzz t||z dz d| | |zzdzzz zS|d k(r!t|| z dz d| ||zzdzzz S|d k(r6| || z z| ||zzdzz t|| z dz d| ||zzdzzz zS|d k(r9| || z dzz| ||zzdzz t|| z dz d| ||zzdzzz zS|d k(r<| |z|| z dzz| ||zzdzz t|| z dz d| ||zzdzzz zSt||)r^r_r`rarbrd )rWr r)r)rerrErFrGrHrrrrrrrrs rrfz(FiberForceLengthActiveDeGroote2016.fdiffsGKiiC 2r2r2r2r2r3 q= B**BI,=+AAI~bl):Q(>?@ B**ArByL/@1.D,DEFG B**BI,=+AAI~bl):Q(>?@ B**ArByL/@1.D,DEFG GR!++S3y=-@1,DDI~s9})>> from sympy import Symbol >>> from sympy.physics.biomechanics import FiberForceVelocityDeGroote2016 >>> v_M_tilde = Symbol('v_M_tilde') >>> fv_M = FiberForceVelocityDeGroote2016.with_defaults(v_M_tilde) >>> fv_M FiberForceVelocityDeGroote2016(v_M_tilde, -0.318, -8.149, -0.374, 0.886) It's also possible to populate the four constants with your own values too. >>> from sympy import symbols >>> c0, c1, c2, c3 = symbols('c0 c1 c2 c3') >>> fv_M = FiberForceVelocityDeGroote2016(v_M_tilde, c0, c1, c2, c3) >>> fv_M FiberForceVelocityDeGroote2016(v_M_tilde, c0, c1, c2, c3) You don't just have to use symbols as the arguments, it's also possible to use expressions. Let's create a new pair of symbols, ``v_M`` and ``v_M_max``, representing muscle fiber extension velocity and maximum muscle fiber extension velocity respectively. We can then represent ``v_M_tilde`` as an expression, the ratio of these. >>> v_M, v_M_max = symbols('v_M v_M_max') >>> v_M_tilde = v_M/v_M_max >>> fv_M = FiberForceVelocityDeGroote2016.with_defaults(v_M_tilde) >>> fv_M FiberForceVelocityDeGroote2016(v_M/v_M_max, -0.318, -8.149, -0.374, 0.886) To inspect the actual symbolic expression that this function represents, we can call the :meth:`~.doit` method on an instance. We'll use the keyword argument ``evaluate=False`` as this will keep the expression in its canonical form and won't simplify any constants. >>> fv_M.doit(evaluate=False) 0.886 - 0.318*log(-8.149*v_M/v_M_max - 0.374 + sqrt(1 + (-8.149*v_M/v_M_max - 0.374)**2)) The function can also be differentiated. We'll differentiate with respect to v_M using the ``diff`` method on an instance with the single positional argument ``v_M``. >>> fv_M.diff(v_M) 2.591382*(1 + (-8.149*v_M/v_M_max - 0.374)**2)**(-1/2)/v_M_max References ========== .. [1] De Groote, F., Kinney, A. L., Rao, A. V., & Fregly, B. J., Evaluation of direct collocation optimal control problem formulations for solving the muscle redundancy problem, Annals of biomedical engineering, 44(10), (2016) pp. 2922-2936 crtd}td}td}td}||||||S)a Recommended constructor that will use the published constants. Explanation =========== Returns a new instance of the muscle fiber force-velocity function using the four constant values specified in the original publication. These have the values: $c_0 = -0.318$ $c_1 = -8.149$ $c_2 = -0.374$ $c_3 = 0.886$ Parameters ========== v_M_tilde : Any (sympifiable) Normalized muscle fiber extension velocity. -0.318-8.149-0.3740.886rBr v_M_tilderErFrGrHs rrIz,FiberForceVelocityDeGroote2016.with_defaults`s;08_ 8_ 8_ 7^9b"b"--r cy)aEvaluation of basic inputs. Parameters ========== v_M_tilde : Any (sympifiable) Normalized muscle fiber extension velocity. c0 : Any (sympifiable) The first constant in the characteristic equation. The published value is ``-0.318``. c1 : Any (sympifiable) The second constant in the characteristic equation. The published value is ``-8.149``. c2 : Any (sympifiable) The third constant in the characteristic equation. The published value is ``-0.374``. c3 : Any (sympifiable) The fourth constant in the characteristic equation. The published value is ``0.886``. Nr;rs rrz#FiberForceVelocityDeGroote2016.eval~rKr cF|jddj|SrMrNrPs rrOz*FiberForceVelocityDeGroote2016._eval_evalfrRr c |j^}}|rA||d<|jdd|i|}|Dcgc]}|jdd|i|c}\}}} } n|\}}} } |r/|t||z| zt||z| zdzdzzz| zS|t||z| ztt ||z| zdzdzzz| zScc}w)aEvaluate the expression defining the function. Parameters ========== deep : bool Whether ``doit`` should be recursively called. Default is ``True``. evaluate : bool. Whether the SymPy expression should be evaluated as it is constructed. If ``False``, then no constant folding will be conducted which will leave the expression in a more numerically- stable for values of ``v_M_tilde`` that correspond to a sensible operating range for a musculotendon. Default is ``True``. **kwargs : dict[str, Any] Additional keyword argument pairs to be recursively passed to ``doit``. r$r#r`r_r;)rWr(r r r) r)r#r$rXrrYrZrErFrGrHs rr(z#FiberForceVelocityDeGroote2016.doits&!%  I  (E* & :D:E:IBKLQfaff8$8%8LNBB&NBB c"Y,+dByL24E3IA3M.NNOORTT T#blR'$r)|b?P/QST/TWX/X*YYZZ]___MsCc |j\}}}}}|dk(r&||ztt||z|zdzdzz S|dk(r2t||z|ztt||z|zdzdzzS|dk(r&||ztt||z|zdzdzz S|dk(r#|tt||z|zdzdzz S|dk(r t dSt ||)r^r_r`rarbrd)rWr rr rr)r)rerrErFrGrHs rrfz$FiberForceVelocityDeGroote2016.fdiffs%)II! 2r2r q=b5oblR.?@!CaGHH H ]9 r!r)|b'891>> from sympy import Symbol >>> from sympy.physics.biomechanics import FiberForceVelocityInverseDeGroote2016 >>> fv_M = Symbol('fv_M') >>> v_M_tilde = FiberForceVelocityInverseDeGroote2016.with_defaults(fv_M) >>> v_M_tilde FiberForceVelocityInverseDeGroote2016(fv_M, -0.318, -8.149, -0.374, 0.886) It's also possible to populate the four constants with your own values too. >>> from sympy import symbols >>> c0, c1, c2, c3 = symbols('c0 c1 c2 c3') >>> v_M_tilde = FiberForceVelocityInverseDeGroote2016(fv_M, c0, c1, c2, c3) >>> v_M_tilde FiberForceVelocityInverseDeGroote2016(fv_M, c0, c1, c2, c3) To inspect the actual symbolic expression that this function represents, we can call the :meth:`~.doit` method on an instance. We'll use the keyword argument ``evaluate=False`` as this will keep the expression in its canonical form and won't simplify any constants. >>> v_M_tilde.doit(evaluate=False) (-c2 + sinh((-c3 + fv_M)/c0))/c1 The function can also be differentiated. We'll differentiate with respect to fv_M using the ``diff`` method on an instance with the single positional argument ``fv_M``. >>> v_M_tilde.diff(fv_M) cosh((-c3 + fv_M)/c0)/(c0*c1) References ========== .. [1] De Groote, F., Kinney, A. L., Rao, A. V., & Fregly, B. J., Evaluation of direct collocation optimal control problem formulations for solving the muscle redundancy problem, Annals of biomedical engineering, 44(10), (2016) pp. 2922-2936 crtd}td}td}td}||||||S)aRecommended constructor that will use the published constants. Explanation =========== Returns a new instance of the inverse muscle fiber force-velocity function using the four constant values specified in the original publication. These have the values: $c_0 = -0.318$ $c_1 = -8.149$ $c_2 = -0.374$ $c_3 = 0.886$ Parameters ========== fv_M : Any (sympifiable) Normalized muscle fiber extension velocity. rrrrrBrfv_MrErFrGrHs rrIz3FiberForceVelocityInverseDeGroote2016.with_defaults>s;28_ 8_ 8_ 7^4RR((r cy)a Evaluation of basic inputs. Parameters ========== fv_M : Any (sympifiable) Normalized muscle fiber force as a function of muscle fiber extension velocity. c0 : Any (sympifiable) The first constant in the characteristic equation. The published value is ``-0.318``. c1 : Any (sympifiable) The second constant in the characteristic equation. The published value is ``-8.149``. c2 : Any (sympifiable) The third constant in the characteristic equation. The published value is ``-0.374``. c3 : Any (sympifiable) The fourth constant in the characteristic equation. The published value is ``0.886``. Nr;rs rrz*FiberForceVelocityInverseDeGroote2016.eval]s0 r cF|jddj|SrMrNrPs rrOz1FiberForceVelocityInverseDeGroote2016._eval_evalfwrRr c .|j^}}|rA||d<|jdd|i|}|Dcgc]}|jdd|i|c}\}}} } n|\}}} } |rt|| z |z | z |z Stt|| z |z | z |z Scc}w)aEvaluate the expression defining the function. Parameters ========== deep : bool Whether ``doit`` should be recursively called. Default is ``True``. evaluate : bool. Whether the SymPy expression should be evaluated as it is constructed. If ``False``, then no constant folding will be conducted which will leave the expression in a more numerically- stable for values of ``fv_M`` that correspond to a sensible operating range for a musculotendon. Default is ``True``. **kwargs : dict[str, Any] Additional keyword argument pairs to be recursively passed to ``doit``. r$r#r;)rWr(r r) r)r#r$rXrrYrZrErFrGrHs rr(z*FiberForceVelocityInverseDeGroote2016.doit{s& 99y  (E* 4990$0%0DBKLQfaff8$8%8LNBB&NBB $)R(2-r1 1_TBY/23b8"<<Mr[cL|j\}}}}}|dk(rt||z |z ||zz S|dk(r ||z t||z |z z|dz|zz S|dk(r|t||z |z z |dzz S|dk(rd|z S|dk(rt||z |z  ||zz St||r])rWr r r)r)rerrErFrGrHs rrfz+FiberForceVelocityInverseDeGroote2016.fdiffs $yyb"b" q=B'B/ / ]ItTBYN33RU2X> > ]tby"n--r1u4 4 ]b5L ]$)R(("R%0 0 x00r ctSrh)rris rrjz-FiberForceVelocityInverseDeGroote2016.inverses .-r cL|jd}|j|}d|zS)rlrz9\left( \operatorname{fv}^M \right)^{-1} \left( %s \right)rm)r)r*r_fv_Ms rroz,FiberForceVelocityInverseDeGroote2016._latexrr Nrqrrrsr;r rrrsMHT))<  2G=@14 . Tr rT)frozenc^eZdZUdZeed<eed<eed<eed<eed<eed<eed<d Zy ) rzFSimple data container to group together related characteristic curves.tendon_force_lengthtendon_force_length_inversefiber_force_length_passive"fiber_force_length_passive_inversefiber_force_length_activefiber_force_velocityfiber_force_velocity_inversec#K|j|j|j|j|j|j |j yw)z7Iterator support for ``CharacteristicCurveCollection``.N)rrrrrrr)r)s r__iter__z&CharacteristicCurveCollection.__iter__sZ&&&...---555,,,'''///sA$A&N)rr,r-r.r__annotations__rr;r rrrs4P44!<< ;;(CC::55"==0r rN)r. dataclassesrsympy.core.exprrsympy.core.functionrrsympy.core.numbersrr&sympy.functions.elementary.exponentialr r %sympy.functions.elementary.hyperbolicr r (sympy.functions.elementary.miscellaneousr sympy.printing.precedencer__all__rrrrrrrrrr;r rrsH!+<-;<90 -(-`cE$?cELXT+FXTvWK*EWKtP^1LP^fOK)DOKd eE%@eEPZT,GZTz $000r