mbuali's picture
Upload folder using huggingface_hub
d1ceb73 verified
"""Tests for the ``sympy.physics.biomechanics.characteristic.py`` module."""
import pytest
from sympy.core.expr import UnevaluatedExpr
from sympy.core.function import Function
from sympy.core.numbers import Float, Integer
from sympy.core.symbol import Symbol, symbols
from sympy.external.importtools import import_module
from sympy.functions.elementary.exponential import exp, log
from sympy.functions.elementary.hyperbolic import cosh, sinh
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.physics.biomechanics.curve import (
CharacteristicCurveCollection,
CharacteristicCurveFunction,
FiberForceLengthActiveDeGroote2016,
FiberForceLengthPassiveDeGroote2016,
FiberForceLengthPassiveInverseDeGroote2016,
FiberForceVelocityDeGroote2016,
FiberForceVelocityInverseDeGroote2016,
TendonForceLengthDeGroote2016,
TendonForceLengthInverseDeGroote2016,
)
from sympy.printing.c import C89CodePrinter, C99CodePrinter, C11CodePrinter
from sympy.printing.cxx import (
CXX98CodePrinter,
CXX11CodePrinter,
CXX17CodePrinter,
)
from sympy.printing.fortran import FCodePrinter
from sympy.printing.lambdarepr import LambdaPrinter
from sympy.printing.latex import LatexPrinter
from sympy.printing.octave import OctaveCodePrinter
from sympy.printing.numpy import (
CuPyPrinter,
JaxPrinter,
NumPyPrinter,
SciPyPrinter,
)
from sympy.printing.pycode import MpmathPrinter, PythonCodePrinter
from sympy.utilities.lambdify import lambdify
jax = import_module('jax')
numpy = import_module('numpy')
if jax:
jax.config.update('jax_enable_x64', True)
class TestCharacteristicCurveFunction:
@staticmethod
@pytest.mark.parametrize(
'code_printer, expected',
[
(C89CodePrinter, '(a + b)*(c + d)*(e + f)'),
(C99CodePrinter, '(a + b)*(c + d)*(e + f)'),
(C11CodePrinter, '(a + b)*(c + d)*(e + f)'),
(CXX98CodePrinter, '(a + b)*(c + d)*(e + f)'),
(CXX11CodePrinter, '(a + b)*(c + d)*(e + f)'),
(CXX17CodePrinter, '(a + b)*(c + d)*(e + f)'),
(FCodePrinter, ' (a + b)*(c + d)*(e + f)'),
(OctaveCodePrinter, '(a + b).*(c + d).*(e + f)'),
(PythonCodePrinter, '(a + b)*(c + d)*(e + f)'),
(NumPyPrinter, '(a + b)*(c + d)*(e + f)'),
(SciPyPrinter, '(a + b)*(c + d)*(e + f)'),
(CuPyPrinter, '(a + b)*(c + d)*(e + f)'),
(JaxPrinter, '(a + b)*(c + d)*(e + f)'),
(MpmathPrinter, '(a + b)*(c + d)*(e + f)'),
(LambdaPrinter, '(a + b)*(c + d)*(e + f)'),
]
)
def test_print_code_parenthesize(code_printer, expected):
class ExampleFunction(CharacteristicCurveFunction):
@classmethod
def eval(cls, a, b):
pass
def doit(self, **kwargs):
a, b = self.args
return a + b
a, b, c, d, e, f = symbols('a, b, c, d, e, f')
f1 = ExampleFunction(a, b)
f2 = ExampleFunction(c, d)
f3 = ExampleFunction(e, f)
assert code_printer().doprint(f1*f2*f3) == expected
class TestTendonForceLengthDeGroote2016:
@pytest.fixture(autouse=True)
def _tendon_force_length_arguments_fixture(self):
self.l_T_tilde = Symbol('l_T_tilde')
self.c0 = Symbol('c_0')
self.c1 = Symbol('c_1')
self.c2 = Symbol('c_2')
self.c3 = Symbol('c_3')
self.constants = (self.c0, self.c1, self.c2, self.c3)
@staticmethod
def test_class():
assert issubclass(TendonForceLengthDeGroote2016, Function)
assert issubclass(TendonForceLengthDeGroote2016, CharacteristicCurveFunction)
assert TendonForceLengthDeGroote2016.__name__ == 'TendonForceLengthDeGroote2016'
def test_instance(self):
fl_T = TendonForceLengthDeGroote2016(self.l_T_tilde, *self.constants)
assert isinstance(fl_T, TendonForceLengthDeGroote2016)
assert str(fl_T) == 'TendonForceLengthDeGroote2016(l_T_tilde, c_0, c_1, c_2, c_3)'
def test_doit(self):
fl_T = TendonForceLengthDeGroote2016(self.l_T_tilde, *self.constants).doit()
assert fl_T == self.c0*exp(self.c3*(self.l_T_tilde - self.c1)) - self.c2
def test_doit_evaluate_false(self):
fl_T = TendonForceLengthDeGroote2016(self.l_T_tilde, *self.constants).doit(evaluate=False)
assert fl_T == self.c0*exp(self.c3*UnevaluatedExpr(self.l_T_tilde - self.c1)) - self.c2
def test_with_defaults(self):
constants = (
Float('0.2'),
Float('0.995'),
Float('0.25'),
Float('33.93669377311689'),
)
fl_T_manual = TendonForceLengthDeGroote2016(self.l_T_tilde, *constants)
fl_T_constants = TendonForceLengthDeGroote2016.with_defaults(self.l_T_tilde)
assert fl_T_manual == fl_T_constants
def test_differentiate_wrt_l_T_tilde(self):
fl_T = TendonForceLengthDeGroote2016(self.l_T_tilde, *self.constants)
expected = self.c0*self.c3*exp(self.c3*UnevaluatedExpr(-self.c1 + self.l_T_tilde))
assert fl_T.diff(self.l_T_tilde) == expected
def test_differentiate_wrt_c0(self):
fl_T = TendonForceLengthDeGroote2016(self.l_T_tilde, *self.constants)
expected = exp(self.c3*UnevaluatedExpr(-self.c1 + self.l_T_tilde))
assert fl_T.diff(self.c0) == expected
def test_differentiate_wrt_c1(self):
fl_T = TendonForceLengthDeGroote2016(self.l_T_tilde, *self.constants)
expected = -self.c0*self.c3*exp(self.c3*UnevaluatedExpr(self.l_T_tilde - self.c1))
assert fl_T.diff(self.c1) == expected
def test_differentiate_wrt_c2(self):
fl_T = TendonForceLengthDeGroote2016(self.l_T_tilde, *self.constants)
expected = Integer(-1)
assert fl_T.diff(self.c2) == expected
def test_differentiate_wrt_c3(self):
fl_T = TendonForceLengthDeGroote2016(self.l_T_tilde, *self.constants)
expected = self.c0*(self.l_T_tilde - self.c1)*exp(self.c3*UnevaluatedExpr(self.l_T_tilde - self.c1))
assert fl_T.diff(self.c3) == expected
def test_inverse(self):
fl_T = TendonForceLengthDeGroote2016(self.l_T_tilde, *self.constants)
assert fl_T.inverse() is TendonForceLengthInverseDeGroote2016
def test_function_print_latex(self):
fl_T = TendonForceLengthDeGroote2016(self.l_T_tilde, *self.constants)
expected = r'\operatorname{fl}^T \left( l_{T tilde} \right)'
assert LatexPrinter().doprint(fl_T) == expected
def test_expression_print_latex(self):
fl_T = TendonForceLengthDeGroote2016(self.l_T_tilde, *self.constants)
expected = r'c_{0} e^{c_{3} \left(- c_{1} + l_{T tilde}\right)} - c_{2}'
assert LatexPrinter().doprint(fl_T.doit()) == expected
@pytest.mark.parametrize(
'code_printer, expected',
[
(
C89CodePrinter,
'(-0.25 + 0.20000000000000001*exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
(
C99CodePrinter,
'(-0.25 + 0.20000000000000001*exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
(
C11CodePrinter,
'(-0.25 + 0.20000000000000001*exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
(
CXX98CodePrinter,
'(-0.25 + 0.20000000000000001*exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
(
CXX11CodePrinter,
'(-0.25 + 0.20000000000000001*std::exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
(
CXX17CodePrinter,
'(-0.25 + 0.20000000000000001*std::exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
(
FCodePrinter,
' (-0.25d0 + 0.2d0*exp(33.93669377311689d0*(l_T_tilde - 0.995d0)))',
),
(
OctaveCodePrinter,
'(-0.25 + 0.2*exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
(
PythonCodePrinter,
'(-0.25 + 0.2*math.exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
(
NumPyPrinter,
'(-0.25 + 0.2*numpy.exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
(
SciPyPrinter,
'(-0.25 + 0.2*numpy.exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
(
CuPyPrinter,
'(-0.25 + 0.2*cupy.exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
(
JaxPrinter,
'(-0.25 + 0.2*jax.numpy.exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
(
MpmathPrinter,
'(mpmath.mpf((1, 1, -2, 1)) + mpmath.mpf((0, 3602879701896397, -54, 52))'
'*mpmath.exp(mpmath.mpf((0, 9552330089424741, -48, 54))*(l_T_tilde + '
'mpmath.mpf((1, 8962163258467287, -53, 53)))))',
),
(
LambdaPrinter,
'(-0.25 + 0.2*math.exp(33.93669377311689*(l_T_tilde - 0.995)))',
),
]
)
def test_print_code(self, code_printer, expected):
fl_T = TendonForceLengthDeGroote2016.with_defaults(self.l_T_tilde)
assert code_printer().doprint(fl_T) == expected
def test_derivative_print_code(self):
fl_T = TendonForceLengthDeGroote2016.with_defaults(self.l_T_tilde)
dfl_T_dl_T_tilde = fl_T.diff(self.l_T_tilde)
expected = '6.787338754623378*math.exp(33.93669377311689*(l_T_tilde - 0.995))'
assert PythonCodePrinter().doprint(dfl_T_dl_T_tilde) == expected
def test_lambdify(self):
fl_T = TendonForceLengthDeGroote2016.with_defaults(self.l_T_tilde)
fl_T_callable = lambdify(self.l_T_tilde, fl_T)
assert fl_T_callable(1.0) == pytest.approx(-0.013014055039221595)
@pytest.mark.skipif(numpy is None, reason='NumPy not installed')
def test_lambdify_numpy(self):
fl_T = TendonForceLengthDeGroote2016.with_defaults(self.l_T_tilde)
fl_T_callable = lambdify(self.l_T_tilde, fl_T, 'numpy')
l_T_tilde = numpy.array([0.95, 1.0, 1.01, 1.05])
expected = numpy.array([
-0.2065693181344816,
-0.0130140550392216,
0.0827421191989246,
1.04314889144172,
])
numpy.testing.assert_allclose(fl_T_callable(l_T_tilde), expected)
@pytest.mark.skipif(jax is None, reason='JAX not installed')
def test_lambdify_jax(self):
fl_T = TendonForceLengthDeGroote2016.with_defaults(self.l_T_tilde)
fl_T_callable = jax.jit(lambdify(self.l_T_tilde, fl_T, 'jax'))
l_T_tilde = jax.numpy.array([0.95, 1.0, 1.01, 1.05])
expected = jax.numpy.array([
-0.2065693181344816,
-0.0130140550392216,
0.0827421191989246,
1.04314889144172,
])
numpy.testing.assert_allclose(fl_T_callable(l_T_tilde), expected)
class TestTendonForceLengthInverseDeGroote2016:
@pytest.fixture(autouse=True)
def _tendon_force_length_inverse_arguments_fixture(self):
self.fl_T = Symbol('fl_T')
self.c0 = Symbol('c_0')
self.c1 = Symbol('c_1')
self.c2 = Symbol('c_2')
self.c3 = Symbol('c_3')
self.constants = (self.c0, self.c1, self.c2, self.c3)
@staticmethod
def test_class():
assert issubclass(TendonForceLengthInverseDeGroote2016, Function)
assert issubclass(TendonForceLengthInverseDeGroote2016, CharacteristicCurveFunction)
assert TendonForceLengthInverseDeGroote2016.__name__ == 'TendonForceLengthInverseDeGroote2016'
def test_instance(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016(self.fl_T, *self.constants)
assert isinstance(fl_T_inv, TendonForceLengthInverseDeGroote2016)
assert str(fl_T_inv) == 'TendonForceLengthInverseDeGroote2016(fl_T, c_0, c_1, c_2, c_3)'
def test_doit(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016(self.fl_T, *self.constants).doit()
assert fl_T_inv == log((self.fl_T + self.c2)/self.c0)/self.c3 + self.c1
def test_doit_evaluate_false(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016(self.fl_T, *self.constants).doit(evaluate=False)
assert fl_T_inv == log(UnevaluatedExpr((self.fl_T + self.c2)/self.c0))/self.c3 + self.c1
def test_with_defaults(self):
constants = (
Float('0.2'),
Float('0.995'),
Float('0.25'),
Float('33.93669377311689'),
)
fl_T_inv_manual = TendonForceLengthInverseDeGroote2016(self.fl_T, *constants)
fl_T_inv_constants = TendonForceLengthInverseDeGroote2016.with_defaults(self.fl_T)
assert fl_T_inv_manual == fl_T_inv_constants
def test_differentiate_wrt_fl_T(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016(self.fl_T, *self.constants)
expected = 1/(self.c3*(self.fl_T + self.c2))
assert fl_T_inv.diff(self.fl_T) == expected
def test_differentiate_wrt_c0(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016(self.fl_T, *self.constants)
expected = -1/(self.c0*self.c3)
assert fl_T_inv.diff(self.c0) == expected
def test_differentiate_wrt_c1(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016(self.fl_T, *self.constants)
expected = Integer(1)
assert fl_T_inv.diff(self.c1) == expected
def test_differentiate_wrt_c2(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016(self.fl_T, *self.constants)
expected = 1/(self.c3*(self.fl_T + self.c2))
assert fl_T_inv.diff(self.c2) == expected
def test_differentiate_wrt_c3(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016(self.fl_T, *self.constants)
expected = -log(UnevaluatedExpr((self.fl_T + self.c2)/self.c0))/self.c3**2
assert fl_T_inv.diff(self.c3) == expected
def test_inverse(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016(self.fl_T, *self.constants)
assert fl_T_inv.inverse() is TendonForceLengthDeGroote2016
def test_function_print_latex(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016(self.fl_T, *self.constants)
expected = r'\left( \operatorname{fl}^T \right)^{-1} \left( fl_{T} \right)'
assert LatexPrinter().doprint(fl_T_inv) == expected
def test_expression_print_latex(self):
fl_T = TendonForceLengthInverseDeGroote2016(self.fl_T, *self.constants)
expected = r'c_{1} + \frac{\log{\left(\frac{c_{2} + fl_{T}}{c_{0}} \right)}}{c_{3}}'
assert LatexPrinter().doprint(fl_T.doit()) == expected
@pytest.mark.parametrize(
'code_printer, expected',
[
(
C89CodePrinter,
'(0.995 + 0.029466630034306838*log(5.0*fl_T + 1.25))',
),
(
C99CodePrinter,
'(0.995 + 0.029466630034306838*log(5.0*fl_T + 1.25))',
),
(
C11CodePrinter,
'(0.995 + 0.029466630034306838*log(5.0*fl_T + 1.25))',
),
(
CXX98CodePrinter,
'(0.995 + 0.029466630034306838*log(5.0*fl_T + 1.25))',
),
(
CXX11CodePrinter,
'(0.995 + 0.029466630034306838*std::log(5.0*fl_T + 1.25))',
),
(
CXX17CodePrinter,
'(0.995 + 0.029466630034306838*std::log(5.0*fl_T + 1.25))',
),
(
FCodePrinter,
' (0.995d0 + 0.02946663003430684d0*log(5.0d0*fl_T + 1.25d0))',
),
(
OctaveCodePrinter,
'(0.995 + 0.02946663003430684*log(5.0*fl_T + 1.25))',
),
(
PythonCodePrinter,
'(0.995 + 0.02946663003430684*math.log(5.0*fl_T + 1.25))',
),
(
NumPyPrinter,
'(0.995 + 0.02946663003430684*numpy.log(5.0*fl_T + 1.25))',
),
(
SciPyPrinter,
'(0.995 + 0.02946663003430684*numpy.log(5.0*fl_T + 1.25))',
),
(
CuPyPrinter,
'(0.995 + 0.02946663003430684*cupy.log(5.0*fl_T + 1.25))',
),
(
JaxPrinter,
'(0.995 + 0.02946663003430684*jax.numpy.log(5.0*fl_T + 1.25))',
),
(
MpmathPrinter,
'(mpmath.mpf((0, 8962163258467287, -53, 53))'
' + mpmath.mpf((0, 33972711434846347, -60, 55))'
'*mpmath.log(mpmath.mpf((0, 5, 0, 3))*fl_T + mpmath.mpf((0, 5, -2, 3))))',
),
(
LambdaPrinter,
'(0.995 + 0.02946663003430684*math.log(5.0*fl_T + 1.25))',
),
]
)
def test_print_code(self, code_printer, expected):
fl_T_inv = TendonForceLengthInverseDeGroote2016.with_defaults(self.fl_T)
assert code_printer().doprint(fl_T_inv) == expected
def test_derivative_print_code(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016.with_defaults(self.fl_T)
dfl_T_inv_dfl_T = fl_T_inv.diff(self.fl_T)
expected = '1/(33.93669377311689*fl_T + 8.484173443279222)'
assert PythonCodePrinter().doprint(dfl_T_inv_dfl_T) == expected
def test_lambdify(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016.with_defaults(self.fl_T)
fl_T_inv_callable = lambdify(self.fl_T, fl_T_inv)
assert fl_T_inv_callable(0.0) == pytest.approx(1.0015752885)
@pytest.mark.skipif(numpy is None, reason='NumPy not installed')
def test_lambdify_numpy(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016.with_defaults(self.fl_T)
fl_T_inv_callable = lambdify(self.fl_T, fl_T_inv, 'numpy')
fl_T = numpy.array([-0.2, -0.01, 0.0, 1.01, 1.02, 1.05])
expected = numpy.array([
0.9541505769,
1.0003724019,
1.0015752885,
1.0492347951,
1.0494677341,
1.0501557022,
])
numpy.testing.assert_allclose(fl_T_inv_callable(fl_T), expected)
@pytest.mark.skipif(jax is None, reason='JAX not installed')
def test_lambdify_jax(self):
fl_T_inv = TendonForceLengthInverseDeGroote2016.with_defaults(self.fl_T)
fl_T_inv_callable = jax.jit(lambdify(self.fl_T, fl_T_inv, 'jax'))
fl_T = jax.numpy.array([-0.2, -0.01, 0.0, 1.01, 1.02, 1.05])
expected = jax.numpy.array([
0.9541505769,
1.0003724019,
1.0015752885,
1.0492347951,
1.0494677341,
1.0501557022,
])
numpy.testing.assert_allclose(fl_T_inv_callable(fl_T), expected)
class TestFiberForceLengthPassiveDeGroote2016:
@pytest.fixture(autouse=True)
def _fiber_force_length_passive_arguments_fixture(self):
self.l_M_tilde = Symbol('l_M_tilde')
self.c0 = Symbol('c_0')
self.c1 = Symbol('c_1')
self.constants = (self.c0, self.c1)
@staticmethod
def test_class():
assert issubclass(FiberForceLengthPassiveDeGroote2016, Function)
assert issubclass(FiberForceLengthPassiveDeGroote2016, CharacteristicCurveFunction)
assert FiberForceLengthPassiveDeGroote2016.__name__ == 'FiberForceLengthPassiveDeGroote2016'
def test_instance(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016(self.l_M_tilde, *self.constants)
assert isinstance(fl_M_pas, FiberForceLengthPassiveDeGroote2016)
assert str(fl_M_pas) == 'FiberForceLengthPassiveDeGroote2016(l_M_tilde, c_0, c_1)'
def test_doit(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016(self.l_M_tilde, *self.constants).doit()
assert fl_M_pas == (exp((self.c1*(self.l_M_tilde - 1))/self.c0) - 1)/(exp(self.c1) - 1)
def test_doit_evaluate_false(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016(self.l_M_tilde, *self.constants).doit(evaluate=False)
assert fl_M_pas == (exp((self.c1*UnevaluatedExpr(self.l_M_tilde - 1))/self.c0) - 1)/(exp(self.c1) - 1)
def test_with_defaults(self):
constants = (
Float('0.6'),
Float('4.0'),
)
fl_M_pas_manual = FiberForceLengthPassiveDeGroote2016(self.l_M_tilde, *constants)
fl_M_pas_constants = FiberForceLengthPassiveDeGroote2016.with_defaults(self.l_M_tilde)
assert fl_M_pas_manual == fl_M_pas_constants
def test_differentiate_wrt_l_M_tilde(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = self.c1*exp(self.c1*UnevaluatedExpr(self.l_M_tilde - 1)/self.c0)/(self.c0*(exp(self.c1) - 1))
assert fl_M_pas.diff(self.l_M_tilde) == expected
def test_differentiate_wrt_c0(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
-self.c1*exp(self.c1*UnevaluatedExpr(self.l_M_tilde - 1)/self.c0)
*UnevaluatedExpr(self.l_M_tilde - 1)/(self.c0**2*(exp(self.c1) - 1))
)
assert fl_M_pas.diff(self.c0) == expected
def test_differentiate_wrt_c1(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
-exp(self.c1)*(-1 + exp(self.c1*UnevaluatedExpr(self.l_M_tilde - 1)/self.c0))/(exp(self.c1) - 1)**2
+ exp(self.c1*UnevaluatedExpr(self.l_M_tilde - 1)/self.c0)*(self.l_M_tilde - 1)/(self.c0*(exp(self.c1) - 1))
)
assert fl_M_pas.diff(self.c1) == expected
def test_inverse(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016(self.l_M_tilde, *self.constants)
assert fl_M_pas.inverse() is FiberForceLengthPassiveInverseDeGroote2016
def test_function_print_latex(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = r'\operatorname{fl}^M_{pas} \left( l_{M tilde} \right)'
assert LatexPrinter().doprint(fl_M_pas) == expected
def test_expression_print_latex(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = r'\frac{e^{\frac{c_{1} \left(l_{M tilde} - 1\right)}{c_{0}}} - 1}{e^{c_{1}} - 1}'
assert LatexPrinter().doprint(fl_M_pas.doit()) == expected
@pytest.mark.parametrize(
'code_printer, expected',
[
(
C89CodePrinter,
'(0.01865736036377405*(-1 + exp(6.666666666666667*(l_M_tilde - 1))))',
),
(
C99CodePrinter,
'(0.01865736036377405*(-1 + exp(6.666666666666667*(l_M_tilde - 1))))',
),
(
C11CodePrinter,
'(0.01865736036377405*(-1 + exp(6.666666666666667*(l_M_tilde - 1))))',
),
(
CXX98CodePrinter,
'(0.01865736036377405*(-1 + exp(6.666666666666667*(l_M_tilde - 1))))',
),
(
CXX11CodePrinter,
'(0.01865736036377405*(-1 + std::exp(6.666666666666667*(l_M_tilde - 1))))',
),
(
CXX17CodePrinter,
'(0.01865736036377405*(-1 + std::exp(6.666666666666667*(l_M_tilde - 1))))',
),
(
FCodePrinter,
' (0.0186573603637741d0*(-1 + exp(6.666666666666667d0*(l_M_tilde - 1\n'
' @ ))))',
),
(
OctaveCodePrinter,
'(0.0186573603637741*(-1 + exp(6.66666666666667*(l_M_tilde - 1))))',
),
(
PythonCodePrinter,
'(0.0186573603637741*(-1 + math.exp(6.66666666666667*(l_M_tilde - 1))))',
),
(
NumPyPrinter,
'(0.0186573603637741*(-1 + numpy.exp(6.66666666666667*(l_M_tilde - 1))))',
),
(
SciPyPrinter,
'(0.0186573603637741*(-1 + numpy.exp(6.66666666666667*(l_M_tilde - 1))))',
),
(
CuPyPrinter,
'(0.0186573603637741*(-1 + cupy.exp(6.66666666666667*(l_M_tilde - 1))))',
),
(
JaxPrinter,
'(0.0186573603637741*(-1 + jax.numpy.exp(6.66666666666667*(l_M_tilde - 1))))',
),
(
MpmathPrinter,
'(mpmath.mpf((0, 672202249456079, -55, 50))*(-1 + mpmath.exp('
'mpmath.mpf((0, 7505999378950827, -50, 53))*(l_M_tilde - 1))))',
),
(
LambdaPrinter,
'(0.0186573603637741*(-1 + math.exp(6.66666666666667*(l_M_tilde - 1))))',
),
]
)
def test_print_code(self, code_printer, expected):
fl_M_pas = FiberForceLengthPassiveDeGroote2016.with_defaults(self.l_M_tilde)
assert code_printer().doprint(fl_M_pas) == expected
def test_derivative_print_code(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016.with_defaults(self.l_M_tilde)
fl_M_pas_dl_M_tilde = fl_M_pas.diff(self.l_M_tilde)
expected = '0.12438240242516*math.exp(6.66666666666667*(l_M_tilde - 1))'
assert PythonCodePrinter().doprint(fl_M_pas_dl_M_tilde) == expected
def test_lambdify(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016.with_defaults(self.l_M_tilde)
fl_M_pas_callable = lambdify(self.l_M_tilde, fl_M_pas)
assert fl_M_pas_callable(1.0) == pytest.approx(0.0)
@pytest.mark.skipif(numpy is None, reason='NumPy not installed')
def test_lambdify_numpy(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016.with_defaults(self.l_M_tilde)
fl_M_pas_callable = lambdify(self.l_M_tilde, fl_M_pas, 'numpy')
l_M_tilde = numpy.array([0.5, 0.8, 0.9, 1.0, 1.1, 1.2, 1.5])
expected = numpy.array([
-0.0179917778,
-0.0137393336,
-0.0090783522,
0.0,
0.0176822155,
0.0521224686,
0.5043387669,
])
numpy.testing.assert_allclose(fl_M_pas_callable(l_M_tilde), expected)
@pytest.mark.skipif(jax is None, reason='JAX not installed')
def test_lambdify_jax(self):
fl_M_pas = FiberForceLengthPassiveDeGroote2016.with_defaults(self.l_M_tilde)
fl_M_pas_callable = jax.jit(lambdify(self.l_M_tilde, fl_M_pas, 'jax'))
l_M_tilde = jax.numpy.array([0.5, 0.8, 0.9, 1.0, 1.1, 1.2, 1.5])
expected = jax.numpy.array([
-0.0179917778,
-0.0137393336,
-0.0090783522,
0.0,
0.0176822155,
0.0521224686,
0.5043387669,
])
numpy.testing.assert_allclose(fl_M_pas_callable(l_M_tilde), expected)
class TestFiberForceLengthPassiveInverseDeGroote2016:
@pytest.fixture(autouse=True)
def _fiber_force_length_passive_arguments_fixture(self):
self.fl_M_pas = Symbol('fl_M_pas')
self.c0 = Symbol('c_0')
self.c1 = Symbol('c_1')
self.constants = (self.c0, self.c1)
@staticmethod
def test_class():
assert issubclass(FiberForceLengthPassiveInverseDeGroote2016, Function)
assert issubclass(FiberForceLengthPassiveInverseDeGroote2016, CharacteristicCurveFunction)
assert FiberForceLengthPassiveInverseDeGroote2016.__name__ == 'FiberForceLengthPassiveInverseDeGroote2016'
def test_instance(self):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016(self.fl_M_pas, *self.constants)
assert isinstance(fl_M_pas_inv, FiberForceLengthPassiveInverseDeGroote2016)
assert str(fl_M_pas_inv) == 'FiberForceLengthPassiveInverseDeGroote2016(fl_M_pas, c_0, c_1)'
def test_doit(self):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016(self.fl_M_pas, *self.constants).doit()
assert fl_M_pas_inv == self.c0*log(self.fl_M_pas*(exp(self.c1) - 1) + 1)/self.c1 + 1
def test_doit_evaluate_false(self):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016(self.fl_M_pas, *self.constants).doit(evaluate=False)
assert fl_M_pas_inv == self.c0*log(UnevaluatedExpr(self.fl_M_pas*(exp(self.c1) - 1)) + 1)/self.c1 + 1
def test_with_defaults(self):
constants = (
Float('0.6'),
Float('4.0'),
)
fl_M_pas_inv_manual = FiberForceLengthPassiveInverseDeGroote2016(self.fl_M_pas, *constants)
fl_M_pas_inv_constants = FiberForceLengthPassiveInverseDeGroote2016.with_defaults(self.fl_M_pas)
assert fl_M_pas_inv_manual == fl_M_pas_inv_constants
def test_differentiate_wrt_fl_T(self):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016(self.fl_M_pas, *self.constants)
expected = self.c0*(exp(self.c1) - 1)/(self.c1*(self.fl_M_pas*(exp(self.c1) - 1) + 1))
assert fl_M_pas_inv.diff(self.fl_M_pas) == expected
def test_differentiate_wrt_c0(self):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016(self.fl_M_pas, *self.constants)
expected = log(self.fl_M_pas*(exp(self.c1) - 1) + 1)/self.c1
assert fl_M_pas_inv.diff(self.c0) == expected
def test_differentiate_wrt_c1(self):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016(self.fl_M_pas, *self.constants)
expected = (
self.c0*self.fl_M_pas*exp(self.c1)/(self.c1*(self.fl_M_pas*(exp(self.c1) - 1) + 1))
- self.c0*log(self.fl_M_pas*(exp(self.c1) - 1) + 1)/self.c1**2
)
assert fl_M_pas_inv.diff(self.c1) == expected
def test_inverse(self):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016(self.fl_M_pas, *self.constants)
assert fl_M_pas_inv.inverse() is FiberForceLengthPassiveDeGroote2016
def test_function_print_latex(self):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016(self.fl_M_pas, *self.constants)
expected = r'\left( \operatorname{fl}^M_{pas} \right)^{-1} \left( fl_{M pas} \right)'
assert LatexPrinter().doprint(fl_M_pas_inv) == expected
def test_expression_print_latex(self):
fl_T = FiberForceLengthPassiveInverseDeGroote2016(self.fl_M_pas, *self.constants)
expected = r'\frac{c_{0} \log{\left(fl_{M pas} \left(e^{c_{1}} - 1\right) + 1 \right)}}{c_{1}} + 1'
assert LatexPrinter().doprint(fl_T.doit()) == expected
@pytest.mark.parametrize(
'code_printer, expected',
[
(
C89CodePrinter,
'(1 + 0.14999999999999999*log(1 + 53.598150033144236*fl_M_pas))',
),
(
C99CodePrinter,
'(1 + 0.14999999999999999*log(1 + 53.598150033144236*fl_M_pas))',
),
(
C11CodePrinter,
'(1 + 0.14999999999999999*log(1 + 53.598150033144236*fl_M_pas))',
),
(
CXX98CodePrinter,
'(1 + 0.14999999999999999*log(1 + 53.598150033144236*fl_M_pas))',
),
(
CXX11CodePrinter,
'(1 + 0.14999999999999999*std::log(1 + 53.598150033144236*fl_M_pas))',
),
(
CXX17CodePrinter,
'(1 + 0.14999999999999999*std::log(1 + 53.598150033144236*fl_M_pas))',
),
(
FCodePrinter,
' (1 + 0.15d0*log(1.0d0 + 53.5981500331442d0*fl_M_pas))',
),
(
OctaveCodePrinter,
'(1 + 0.15*log(1 + 53.5981500331442*fl_M_pas))',
),
(
PythonCodePrinter,
'(1 + 0.15*math.log(1 + 53.5981500331442*fl_M_pas))',
),
(
NumPyPrinter,
'(1 + 0.15*numpy.log(1 + 53.5981500331442*fl_M_pas))',
),
(
SciPyPrinter,
'(1 + 0.15*numpy.log(1 + 53.5981500331442*fl_M_pas))',
),
(
CuPyPrinter,
'(1 + 0.15*cupy.log(1 + 53.5981500331442*fl_M_pas))',
),
(
JaxPrinter,
'(1 + 0.15*jax.numpy.log(1 + 53.5981500331442*fl_M_pas))',
),
(
MpmathPrinter,
'(1 + mpmath.mpf((0, 5404319552844595, -55, 53))*mpmath.log(1 '
'+ mpmath.mpf((0, 942908627019595, -44, 50))*fl_M_pas))',
),
(
LambdaPrinter,
'(1 + 0.15*math.log(1 + 53.5981500331442*fl_M_pas))',
),
]
)
def test_print_code(self, code_printer, expected):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016.with_defaults(self.fl_M_pas)
assert code_printer().doprint(fl_M_pas_inv) == expected
def test_derivative_print_code(self):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016.with_defaults(self.fl_M_pas)
dfl_M_pas_inv_dfl_T = fl_M_pas_inv.diff(self.fl_M_pas)
expected = '32.1588900198865/(214.392600132577*fl_M_pas + 4.0)'
assert PythonCodePrinter().doprint(dfl_M_pas_inv_dfl_T) == expected
def test_lambdify(self):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016.with_defaults(self.fl_M_pas)
fl_M_pas_inv_callable = lambdify(self.fl_M_pas, fl_M_pas_inv)
assert fl_M_pas_inv_callable(0.0) == pytest.approx(1.0)
@pytest.mark.skipif(numpy is None, reason='NumPy not installed')
def test_lambdify_numpy(self):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016.with_defaults(self.fl_M_pas)
fl_M_pas_inv_callable = lambdify(self.fl_M_pas, fl_M_pas_inv, 'numpy')
fl_M_pas = numpy.array([-0.01, 0.0, 0.01, 0.02, 0.05, 0.1])
expected = numpy.array([
0.8848253714,
1.0,
1.0643754386,
1.1092744701,
1.1954331425,
1.2774998934,
])
numpy.testing.assert_allclose(fl_M_pas_inv_callable(fl_M_pas), expected)
@pytest.mark.skipif(jax is None, reason='JAX not installed')
def test_lambdify_jax(self):
fl_M_pas_inv = FiberForceLengthPassiveInverseDeGroote2016.with_defaults(self.fl_M_pas)
fl_M_pas_inv_callable = jax.jit(lambdify(self.fl_M_pas, fl_M_pas_inv, 'jax'))
fl_M_pas = jax.numpy.array([-0.01, 0.0, 0.01, 0.02, 0.05, 0.1])
expected = jax.numpy.array([
0.8848253714,
1.0,
1.0643754386,
1.1092744701,
1.1954331425,
1.2774998934,
])
numpy.testing.assert_allclose(fl_M_pas_inv_callable(fl_M_pas), expected)
class TestFiberForceLengthActiveDeGroote2016:
@pytest.fixture(autouse=True)
def _fiber_force_length_active_arguments_fixture(self):
self.l_M_tilde = Symbol('l_M_tilde')
self.c0 = Symbol('c_0')
self.c1 = Symbol('c_1')
self.c2 = Symbol('c_2')
self.c3 = Symbol('c_3')
self.c4 = Symbol('c_4')
self.c5 = Symbol('c_5')
self.c6 = Symbol('c_6')
self.c7 = Symbol('c_7')
self.c8 = Symbol('c_8')
self.c9 = Symbol('c_9')
self.c10 = Symbol('c_10')
self.c11 = Symbol('c_11')
self.constants = (
self.c0, self.c1, self.c2, self.c3, self.c4, self.c5,
self.c6, self.c7, self.c8, self.c9, self.c10, self.c11,
)
@staticmethod
def test_class():
assert issubclass(FiberForceLengthActiveDeGroote2016, Function)
assert issubclass(FiberForceLengthActiveDeGroote2016, CharacteristicCurveFunction)
assert FiberForceLengthActiveDeGroote2016.__name__ == 'FiberForceLengthActiveDeGroote2016'
def test_instance(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
assert isinstance(fl_M_act, FiberForceLengthActiveDeGroote2016)
assert str(fl_M_act) == (
'FiberForceLengthActiveDeGroote2016(l_M_tilde, c_0, c_1, c_2, c_3, '
'c_4, c_5, c_6, c_7, c_8, c_9, c_10, c_11)'
)
def test_doit(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants).doit()
assert fl_M_act == (
self.c0*exp(-(((self.l_M_tilde - self.c1)/(self.c2 + self.c3*self.l_M_tilde))**2)/2)
+ self.c4*exp(-(((self.l_M_tilde - self.c5)/(self.c6 + self.c7*self.l_M_tilde))**2)/2)
+ self.c8*exp(-(((self.l_M_tilde - self.c9)/(self.c10 + self.c11*self.l_M_tilde))**2)/2)
)
def test_doit_evaluate_false(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants).doit(evaluate=False)
assert fl_M_act == (
self.c0*exp(-((UnevaluatedExpr(self.l_M_tilde - self.c1)/(self.c2 + self.c3*self.l_M_tilde))**2)/2)
+ self.c4*exp(-((UnevaluatedExpr(self.l_M_tilde - self.c5)/(self.c6 + self.c7*self.l_M_tilde))**2)/2)
+ self.c8*exp(-((UnevaluatedExpr(self.l_M_tilde - self.c9)/(self.c10 + self.c11*self.l_M_tilde))**2)/2)
)
def test_with_defaults(self):
constants = (
Float('0.814'),
Float('1.06'),
Float('0.162'),
Float('0.0633'),
Float('0.433'),
Float('0.717'),
Float('-0.0299'),
Float('0.2'),
Float('0.1'),
Float('1.0'),
Float('0.354'),
Float('0.0'),
)
fl_M_act_manual = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *constants)
fl_M_act_constants = FiberForceLengthActiveDeGroote2016.with_defaults(self.l_M_tilde)
assert fl_M_act_manual == fl_M_act_constants
def test_differentiate_wrt_l_M_tilde(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
self.c0*(
self.c3*(self.l_M_tilde - self.c1)**2/(self.c2 + self.c3*self.l_M_tilde)**3
+ (self.c1 - self.l_M_tilde)/((self.c2 + self.c3*self.l_M_tilde)**2)
)*exp(-(self.l_M_tilde - self.c1)**2/(2*(self.c2 + self.c3*self.l_M_tilde)**2))
+ self.c4*(
self.c7*(self.l_M_tilde - self.c5)**2/(self.c6 + self.c7*self.l_M_tilde)**3
+ (self.c5 - self.l_M_tilde)/((self.c6 + self.c7*self.l_M_tilde)**2)
)*exp(-(self.l_M_tilde - self.c5)**2/(2*(self.c6 + self.c7*self.l_M_tilde)**2))
+ self.c8*(
self.c11*(self.l_M_tilde - self.c9)**2/(self.c10 + self.c11*self.l_M_tilde)**3
+ (self.c9 - self.l_M_tilde)/((self.c10 + self.c11*self.l_M_tilde)**2)
)*exp(-(self.l_M_tilde - self.c9)**2/(2*(self.c10 + self.c11*self.l_M_tilde)**2))
)
assert fl_M_act.diff(self.l_M_tilde) == expected
def test_differentiate_wrt_c0(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = exp(-(self.l_M_tilde - self.c1)**2/(2*(self.c2 + self.c3*self.l_M_tilde)**2))
assert fl_M_act.doit().diff(self.c0) == expected
def test_differentiate_wrt_c1(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
self.c0*(self.l_M_tilde - self.c1)/(self.c2 + self.c3*self.l_M_tilde)**2
*exp(-(self.l_M_tilde - self.c1)**2/(2*(self.c2 + self.c3*self.l_M_tilde)**2))
)
assert fl_M_act.diff(self.c1) == expected
def test_differentiate_wrt_c2(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
self.c0*(self.l_M_tilde - self.c1)**2/(self.c2 + self.c3*self.l_M_tilde)**3
*exp(-(self.l_M_tilde - self.c1)**2/(2*(self.c2 + self.c3*self.l_M_tilde)**2))
)
assert fl_M_act.diff(self.c2) == expected
def test_differentiate_wrt_c3(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
self.c0*self.l_M_tilde*(self.l_M_tilde - self.c1)**2/(self.c2 + self.c3*self.l_M_tilde)**3
*exp(-(self.l_M_tilde - self.c1)**2/(2*(self.c2 + self.c3*self.l_M_tilde)**2))
)
assert fl_M_act.diff(self.c3) == expected
def test_differentiate_wrt_c4(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = exp(-(self.l_M_tilde - self.c5)**2/(2*(self.c6 + self.c7*self.l_M_tilde)**2))
assert fl_M_act.diff(self.c4) == expected
def test_differentiate_wrt_c5(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
self.c4*(self.l_M_tilde - self.c5)/(self.c6 + self.c7*self.l_M_tilde)**2
*exp(-(self.l_M_tilde - self.c5)**2/(2*(self.c6 + self.c7*self.l_M_tilde)**2))
)
assert fl_M_act.diff(self.c5) == expected
def test_differentiate_wrt_c6(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
self.c4*(self.l_M_tilde - self.c5)**2/(self.c6 + self.c7*self.l_M_tilde)**3
*exp(-(self.l_M_tilde - self.c5)**2/(2*(self.c6 + self.c7*self.l_M_tilde)**2))
)
assert fl_M_act.diff(self.c6) == expected
def test_differentiate_wrt_c7(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
self.c4*self.l_M_tilde*(self.l_M_tilde - self.c5)**2/(self.c6 + self.c7*self.l_M_tilde)**3
*exp(-(self.l_M_tilde - self.c5)**2/(2*(self.c6 + self.c7*self.l_M_tilde)**2))
)
assert fl_M_act.diff(self.c7) == expected
def test_differentiate_wrt_c8(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = exp(-(self.l_M_tilde - self.c9)**2/(2*(self.c10 + self.c11*self.l_M_tilde)**2))
assert fl_M_act.diff(self.c8) == expected
def test_differentiate_wrt_c9(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
self.c8*(self.l_M_tilde - self.c9)/(self.c10 + self.c11*self.l_M_tilde)**2
*exp(-(self.l_M_tilde - self.c9)**2/(2*(self.c10 + self.c11*self.l_M_tilde)**2))
)
assert fl_M_act.diff(self.c9) == expected
def test_differentiate_wrt_c10(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
self.c8*(self.l_M_tilde - self.c9)**2/(self.c10 + self.c11*self.l_M_tilde)**3
*exp(-(self.l_M_tilde - self.c9)**2/(2*(self.c10 + self.c11*self.l_M_tilde)**2))
)
assert fl_M_act.diff(self.c10) == expected
def test_differentiate_wrt_c11(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
self.c8*self.l_M_tilde*(self.l_M_tilde - self.c9)**2/(self.c10 + self.c11*self.l_M_tilde)**3
*exp(-(self.l_M_tilde - self.c9)**2/(2*(self.c10 + self.c11*self.l_M_tilde)**2))
)
assert fl_M_act.diff(self.c11) == expected
def test_function_print_latex(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = r'\operatorname{fl}^M_{act} \left( l_{M tilde} \right)'
assert LatexPrinter().doprint(fl_M_act) == expected
def test_expression_print_latex(self):
fl_M_act = FiberForceLengthActiveDeGroote2016(self.l_M_tilde, *self.constants)
expected = (
r'c_{0} e^{- \frac{\left(- c_{1} + l_{M tilde}\right)^{2}}{2 \left(c_{2} + c_{3} l_{M tilde}\right)^{2}}} '
r'+ c_{4} e^{- \frac{\left(- c_{5} + l_{M tilde}\right)^{2}}{2 \left(c_{6} + c_{7} l_{M tilde}\right)^{2}}} '
r'+ c_{8} e^{- \frac{\left(- c_{9} + l_{M tilde}\right)^{2}}{2 \left(c_{10} + c_{11} l_{M tilde}\right)^{2}}}'
)
assert LatexPrinter().doprint(fl_M_act.doit()) == expected
@pytest.mark.parametrize(
'code_printer, expected',
[
(
C89CodePrinter,
(
'(0.81399999999999995*exp(-19.051973784484073'
'*pow(l_M_tilde - 1.0600000000000001, 2)'
'/pow(0.39074074074074072*l_M_tilde + 1, 2)) '
'+ 0.433*exp(-12.499999999999998'
'*pow(l_M_tilde - 0.71699999999999997, 2)'
'/pow(l_M_tilde - 0.14949999999999999, 2)) '
'+ 0.10000000000000001*exp(-3.9899134986753491'
'*pow(l_M_tilde - 1.0, 2)))'
),
),
(
C99CodePrinter,
(
'(0.81399999999999995*exp(-19.051973784484073'
'*pow(l_M_tilde - 1.0600000000000001, 2)'
'/pow(0.39074074074074072*l_M_tilde + 1, 2)) '
'+ 0.433*exp(-12.499999999999998'
'*pow(l_M_tilde - 0.71699999999999997, 2)'
'/pow(l_M_tilde - 0.14949999999999999, 2)) '
'+ 0.10000000000000001*exp(-3.9899134986753491'
'*pow(l_M_tilde - 1.0, 2)))'
),
),
(
C11CodePrinter,
(
'(0.81399999999999995*exp(-19.051973784484073'
'*pow(l_M_tilde - 1.0600000000000001, 2)'
'/pow(0.39074074074074072*l_M_tilde + 1, 2)) '
'+ 0.433*exp(-12.499999999999998'
'*pow(l_M_tilde - 0.71699999999999997, 2)'
'/pow(l_M_tilde - 0.14949999999999999, 2)) '
'+ 0.10000000000000001*exp(-3.9899134986753491'
'*pow(l_M_tilde - 1.0, 2)))'
),
),
(
CXX98CodePrinter,
(
'(0.81399999999999995*exp(-19.051973784484073'
'*std::pow(l_M_tilde - 1.0600000000000001, 2)'
'/std::pow(0.39074074074074072*l_M_tilde + 1, 2)) '
'+ 0.433*exp(-12.499999999999998'
'*std::pow(l_M_tilde - 0.71699999999999997, 2)'
'/std::pow(l_M_tilde - 0.14949999999999999, 2)) '
'+ 0.10000000000000001*exp(-3.9899134986753491'
'*std::pow(l_M_tilde - 1.0, 2)))'
),
),
(
CXX11CodePrinter,
(
'(0.81399999999999995*std::exp(-19.051973784484073'
'*std::pow(l_M_tilde - 1.0600000000000001, 2)'
'/std::pow(0.39074074074074072*l_M_tilde + 1, 2)) '
'+ 0.433*std::exp(-12.499999999999998'
'*std::pow(l_M_tilde - 0.71699999999999997, 2)'
'/std::pow(l_M_tilde - 0.14949999999999999, 2)) '
'+ 0.10000000000000001*std::exp(-3.9899134986753491'
'*std::pow(l_M_tilde - 1.0, 2)))'
),
),
(
CXX17CodePrinter,
(
'(0.81399999999999995*std::exp(-19.051973784484073'
'*std::pow(l_M_tilde - 1.0600000000000001, 2)'
'/std::pow(0.39074074074074072*l_M_tilde + 1, 2)) '
'+ 0.433*std::exp(-12.499999999999998'
'*std::pow(l_M_tilde - 0.71699999999999997, 2)'
'/std::pow(l_M_tilde - 0.14949999999999999, 2)) '
'+ 0.10000000000000001*std::exp(-3.9899134986753491'
'*std::pow(l_M_tilde - 1.0, 2)))'
),
),
(
FCodePrinter,
(
' (0.814d0*exp(-19.051973784484073d0*(l_M_tilde - 1.06d0)**2/(\n'
' @ 0.39074074074074072d0*l_M_tilde + 1.0d0)**2) + 0.433d0*exp(\n'
' @ -12.499999999999998d0*(l_M_tilde - 0.717d0)**2/(l_M_tilde -\n'
' @ 0.14949999999999999d0)**2) + 0.1d0*exp(-3.9899134986753491d0*(\n'
' @ l_M_tilde - 1.0d0)**2))'
),
),
(
OctaveCodePrinter,
(
'(0.814*exp(-19.0519737844841*(l_M_tilde - 1.06).^2'
'./(0.390740740740741*l_M_tilde + 1).^2) '
'+ 0.433*exp(-12.5*(l_M_tilde - 0.717).^2'
'./(l_M_tilde - 0.1495).^2) '
'+ 0.1*exp(-3.98991349867535*(l_M_tilde - 1.0).^2))'
),
),
(
PythonCodePrinter,
(
'(0.814*math.exp(-19.0519737844841*(l_M_tilde - 1.06)**2'
'/(0.390740740740741*l_M_tilde + 1)**2) '
'+ 0.433*math.exp(-12.5*(l_M_tilde - 0.717)**2'
'/(l_M_tilde - 0.1495)**2) '
'+ 0.1*math.exp(-3.98991349867535*(l_M_tilde - 1.0)**2))'
),
),
(
NumPyPrinter,
(
'(0.814*numpy.exp(-19.0519737844841*(l_M_tilde - 1.06)**2'
'/(0.390740740740741*l_M_tilde + 1)**2) '
'+ 0.433*numpy.exp(-12.5*(l_M_tilde - 0.717)**2'
'/(l_M_tilde - 0.1495)**2) '
'+ 0.1*numpy.exp(-3.98991349867535*(l_M_tilde - 1.0)**2))'
),
),
(
SciPyPrinter,
(
'(0.814*numpy.exp(-19.0519737844841*(l_M_tilde - 1.06)**2'
'/(0.390740740740741*l_M_tilde + 1)**2) '
'+ 0.433*numpy.exp(-12.5*(l_M_tilde - 0.717)**2'
'/(l_M_tilde - 0.1495)**2) '
'+ 0.1*numpy.exp(-3.98991349867535*(l_M_tilde - 1.0)**2))'
),
),
(
CuPyPrinter,
(
'(0.814*cupy.exp(-19.0519737844841*(l_M_tilde - 1.06)**2'
'/(0.390740740740741*l_M_tilde + 1)**2) '
'+ 0.433*cupy.exp(-12.5*(l_M_tilde - 0.717)**2'
'/(l_M_tilde - 0.1495)**2) '
'+ 0.1*cupy.exp(-3.98991349867535*(l_M_tilde - 1.0)**2))'
),
),
(
JaxPrinter,
(
'(0.814*jax.numpy.exp(-19.0519737844841*(l_M_tilde - 1.06)**2'
'/(0.390740740740741*l_M_tilde + 1)**2) '
'+ 0.433*jax.numpy.exp(-12.5*(l_M_tilde - 0.717)**2'
'/(l_M_tilde - 0.1495)**2) '
'+ 0.1*jax.numpy.exp(-3.98991349867535*(l_M_tilde - 1.0)**2))'
),
),
(
MpmathPrinter,
(
'(mpmath.mpf((0, 7331860193359167, -53, 53))'
'*mpmath.exp(-mpmath.mpf((0, 5362653877279683, -48, 53))'
'*(l_M_tilde + mpmath.mpf((1, 2386907802506363, -51, 52)))**2'
'/(mpmath.mpf((0, 3519479708796943, -53, 52))*l_M_tilde + 1)**2) '
'+ mpmath.mpf((0, 7800234554605699, -54, 53))'
'*mpmath.exp(-mpmath.mpf((0, 7036874417766399, -49, 53))'
'*(l_M_tilde + mpmath.mpf((1, 6458161865649291, -53, 53)))**2'
'/(l_M_tilde + mpmath.mpf((1, 5386305154335113, -55, 53)))**2) '
'+ mpmath.mpf((0, 3602879701896397, -55, 52))'
'*mpmath.exp(-mpmath.mpf((0, 8984486472937407, -51, 53))'
'*(l_M_tilde + mpmath.mpf((1, 1, 0, 1)))**2))'
),
),
(
LambdaPrinter,
(
'(0.814*math.exp(-19.0519737844841*(l_M_tilde - 1.06)**2'
'/(0.390740740740741*l_M_tilde + 1)**2) '
'+ 0.433*math.exp(-12.5*(l_M_tilde - 0.717)**2'
'/(l_M_tilde - 0.1495)**2) '
'+ 0.1*math.exp(-3.98991349867535*(l_M_tilde - 1.0)**2))'
),
),
]
)
def test_print_code(self, code_printer, expected):
fl_M_act = FiberForceLengthActiveDeGroote2016.with_defaults(self.l_M_tilde)
assert code_printer().doprint(fl_M_act) == expected
def test_derivative_print_code(self):
fl_M_act = FiberForceLengthActiveDeGroote2016.with_defaults(self.l_M_tilde)
fl_M_act_dl_M_tilde = fl_M_act.diff(self.l_M_tilde)
expected = (
'(0.79798269973507 - 0.79798269973507*l_M_tilde)'
'*math.exp(-3.98991349867535*(l_M_tilde - 1.0)**2) '
'+ (10.825*(0.717 - l_M_tilde)/(l_M_tilde - 0.1495)**2 '
'+ 10.825*(l_M_tilde - 0.717)**2/(l_M_tilde - 0.1495)**3)'
'*math.exp(-12.5*(l_M_tilde - 0.717)**2/(l_M_tilde - 0.1495)**2) '
'+ (31.0166133211401*(1.06 - l_M_tilde)/(0.390740740740741*l_M_tilde + 1)**2 '
'+ 13.6174190361677*(0.943396226415094*l_M_tilde - 1)**2'
'/(0.390740740740741*l_M_tilde + 1)**3)'
'*math.exp(-21.4067977442463*(0.943396226415094*l_M_tilde - 1)**2'
'/(0.390740740740741*l_M_tilde + 1)**2)'
)
assert PythonCodePrinter().doprint(fl_M_act_dl_M_tilde) == expected
def test_lambdify(self):
fl_M_act = FiberForceLengthActiveDeGroote2016.with_defaults(self.l_M_tilde)
fl_M_act_callable = lambdify(self.l_M_tilde, fl_M_act)
assert fl_M_act_callable(1.0) == pytest.approx(0.9941398866)
@pytest.mark.skipif(numpy is None, reason='NumPy not installed')
def test_lambdify_numpy(self):
fl_M_act = FiberForceLengthActiveDeGroote2016.with_defaults(self.l_M_tilde)
fl_M_act_callable = lambdify(self.l_M_tilde, fl_M_act, 'numpy')
l_M_tilde = numpy.array([0.0, 0.5, 1.0, 1.5, 2.0])
expected = numpy.array([
0.0018501319,
0.0529122812,
0.9941398866,
0.2312431531,
0.0069595432,
])
numpy.testing.assert_allclose(fl_M_act_callable(l_M_tilde), expected)
@pytest.mark.skipif(jax is None, reason='JAX not installed')
def test_lambdify_jax(self):
fl_M_act = FiberForceLengthActiveDeGroote2016.with_defaults(self.l_M_tilde)
fl_M_act_callable = jax.jit(lambdify(self.l_M_tilde, fl_M_act, 'jax'))
l_M_tilde = jax.numpy.array([0.0, 0.5, 1.0, 1.5, 2.0])
expected = jax.numpy.array([
0.0018501319,
0.0529122812,
0.9941398866,
0.2312431531,
0.0069595432,
])
numpy.testing.assert_allclose(fl_M_act_callable(l_M_tilde), expected)
class TestFiberForceVelocityDeGroote2016:
@pytest.fixture(autouse=True)
def _muscle_fiber_force_velocity_arguments_fixture(self):
self.v_M_tilde = Symbol('v_M_tilde')
self.c0 = Symbol('c_0')
self.c1 = Symbol('c_1')
self.c2 = Symbol('c_2')
self.c3 = Symbol('c_3')
self.constants = (self.c0, self.c1, self.c2, self.c3)
@staticmethod
def test_class():
assert issubclass(FiberForceVelocityDeGroote2016, Function)
assert issubclass(FiberForceVelocityDeGroote2016, CharacteristicCurveFunction)
assert FiberForceVelocityDeGroote2016.__name__ == 'FiberForceVelocityDeGroote2016'
def test_instance(self):
fv_M = FiberForceVelocityDeGroote2016(self.v_M_tilde, *self.constants)
assert isinstance(fv_M, FiberForceVelocityDeGroote2016)
assert str(fv_M) == 'FiberForceVelocityDeGroote2016(v_M_tilde, c_0, c_1, c_2, c_3)'
def test_doit(self):
fv_M = FiberForceVelocityDeGroote2016(self.v_M_tilde, *self.constants).doit()
expected = (
self.c0 * log((self.c1 * self.v_M_tilde + self.c2)
+ sqrt((self.c1 * self.v_M_tilde + self.c2)**2 + 1)) + self.c3
)
assert fv_M == expected
def test_doit_evaluate_false(self):
fv_M = FiberForceVelocityDeGroote2016(self.v_M_tilde, *self.constants).doit(evaluate=False)
expected = (
self.c0 * log((self.c1 * self.v_M_tilde + self.c2)
+ sqrt(UnevaluatedExpr(self.c1 * self.v_M_tilde + self.c2)**2 + 1)) + self.c3
)
assert fv_M == expected
def test_with_defaults(self):
constants = (
Float('-0.318'),
Float('-8.149'),
Float('-0.374'),
Float('0.886'),
)
fv_M_manual = FiberForceVelocityDeGroote2016(self.v_M_tilde, *constants)
fv_M_constants = FiberForceVelocityDeGroote2016.with_defaults(self.v_M_tilde)
assert fv_M_manual == fv_M_constants
def test_differentiate_wrt_v_M_tilde(self):
fv_M = FiberForceVelocityDeGroote2016(self.v_M_tilde, *self.constants)
expected = (
self.c0*self.c1
/sqrt(UnevaluatedExpr(self.c1*self.v_M_tilde + self.c2)**2 + 1)
)
assert fv_M.diff(self.v_M_tilde) == expected
def test_differentiate_wrt_c0(self):
fv_M = FiberForceVelocityDeGroote2016(self.v_M_tilde, *self.constants)
expected = log(
self.c1*self.v_M_tilde + self.c2
+ sqrt(UnevaluatedExpr(self.c1*self.v_M_tilde + self.c2)**2 + 1)
)
assert fv_M.diff(self.c0) == expected
def test_differentiate_wrt_c1(self):
fv_M = FiberForceVelocityDeGroote2016(self.v_M_tilde, *self.constants)
expected = (
self.c0*self.v_M_tilde
/sqrt(UnevaluatedExpr(self.c1*self.v_M_tilde + self.c2)**2 + 1)
)
assert fv_M.diff(self.c1) == expected
def test_differentiate_wrt_c2(self):
fv_M = FiberForceVelocityDeGroote2016(self.v_M_tilde, *self.constants)
expected = (
self.c0
/sqrt(UnevaluatedExpr(self.c1*self.v_M_tilde + self.c2)**2 + 1)
)
assert fv_M.diff(self.c2) == expected
def test_differentiate_wrt_c3(self):
fv_M = FiberForceVelocityDeGroote2016(self.v_M_tilde, *self.constants)
expected = Integer(1)
assert fv_M.diff(self.c3) == expected
def test_inverse(self):
fv_M = FiberForceVelocityDeGroote2016(self.v_M_tilde, *self.constants)
assert fv_M.inverse() is FiberForceVelocityInverseDeGroote2016
def test_function_print_latex(self):
fv_M = FiberForceVelocityDeGroote2016(self.v_M_tilde, *self.constants)
expected = r'\operatorname{fv}^M \left( v_{M tilde} \right)'
assert LatexPrinter().doprint(fv_M) == expected
def test_expression_print_latex(self):
fv_M = FiberForceVelocityDeGroote2016(self.v_M_tilde, *self.constants)
expected = (
r'c_{0} \log{\left(c_{1} v_{M tilde} + c_{2} + \sqrt{\left(c_{1} '
r'v_{M tilde} + c_{2}\right)^{2} + 1} \right)} + c_{3}'
)
assert LatexPrinter().doprint(fv_M.doit()) == expected
@pytest.mark.parametrize(
'code_printer, expected',
[
(
C89CodePrinter,
'(0.88600000000000001 - 0.318*log(-8.1489999999999991*v_M_tilde '
'- 0.374 + sqrt(1 + pow(-8.1489999999999991*v_M_tilde - 0.374, 2))))',
),
(
C99CodePrinter,
'(0.88600000000000001 - 0.318*log(-8.1489999999999991*v_M_tilde '
'- 0.374 + sqrt(1 + pow(-8.1489999999999991*v_M_tilde - 0.374, 2))))',
),
(
C11CodePrinter,
'(0.88600000000000001 - 0.318*log(-8.1489999999999991*v_M_tilde '
'- 0.374 + sqrt(1 + pow(-8.1489999999999991*v_M_tilde - 0.374, 2))))',
),
(
CXX98CodePrinter,
'(0.88600000000000001 - 0.318*log(-8.1489999999999991*v_M_tilde '
'- 0.374 + std::sqrt(1 + std::pow(-8.1489999999999991*v_M_tilde - 0.374, 2))))',
),
(
CXX11CodePrinter,
'(0.88600000000000001 - 0.318*std::log(-8.1489999999999991*v_M_tilde '
'- 0.374 + std::sqrt(1 + std::pow(-8.1489999999999991*v_M_tilde - 0.374, 2))))',
),
(
CXX17CodePrinter,
'(0.88600000000000001 - 0.318*std::log(-8.1489999999999991*v_M_tilde '
'- 0.374 + std::sqrt(1 + std::pow(-8.1489999999999991*v_M_tilde - 0.374, 2))))',
),
(
FCodePrinter,
' (0.886d0 - 0.318d0*log(-8.1489999999999991d0*v_M_tilde - 0.374d0 +\n'
' @ sqrt(1.0d0 + (-8.149d0*v_M_tilde - 0.374d0)**2)))',
),
(
OctaveCodePrinter,
'(0.886 - 0.318*log(-8.149*v_M_tilde - 0.374 '
'+ sqrt(1 + (-8.149*v_M_tilde - 0.374).^2)))',
),
(
PythonCodePrinter,
'(0.886 - 0.318*math.log(-8.149*v_M_tilde - 0.374 '
'+ math.sqrt(1 + (-8.149*v_M_tilde - 0.374)**2)))',
),
(
NumPyPrinter,
'(0.886 - 0.318*numpy.log(-8.149*v_M_tilde - 0.374 '
'+ numpy.sqrt(1 + (-8.149*v_M_tilde - 0.374)**2)))',
),
(
SciPyPrinter,
'(0.886 - 0.318*numpy.log(-8.149*v_M_tilde - 0.374 '
'+ numpy.sqrt(1 + (-8.149*v_M_tilde - 0.374)**2)))',
),
(
CuPyPrinter,
'(0.886 - 0.318*cupy.log(-8.149*v_M_tilde - 0.374 '
'+ cupy.sqrt(1 + (-8.149*v_M_tilde - 0.374)**2)))',
),
(
JaxPrinter,
'(0.886 - 0.318*jax.numpy.log(-8.149*v_M_tilde - 0.374 '
'+ jax.numpy.sqrt(1 + (-8.149*v_M_tilde - 0.374)**2)))',
),
(
MpmathPrinter,
'(mpmath.mpf((0, 7980378539700519, -53, 53)) '
'- mpmath.mpf((0, 5728578726015271, -54, 53))'
'*mpmath.log(-mpmath.mpf((0, 4587479170430271, -49, 53))*v_M_tilde '
'+ mpmath.mpf((1, 3368692521273131, -53, 52)) '
'+ mpmath.sqrt(1 + (-mpmath.mpf((0, 4587479170430271, -49, 53))*v_M_tilde '
'+ mpmath.mpf((1, 3368692521273131, -53, 52)))**2)))',
),
(
LambdaPrinter,
'(0.886 - 0.318*math.log(-8.149*v_M_tilde - 0.374 '
'+ sqrt(1 + (-8.149*v_M_tilde - 0.374)**2)))',
),
]
)
def test_print_code(self, code_printer, expected):
fv_M = FiberForceVelocityDeGroote2016.with_defaults(self.v_M_tilde)
assert code_printer().doprint(fv_M) == expected
def test_derivative_print_code(self):
fv_M = FiberForceVelocityDeGroote2016.with_defaults(self.v_M_tilde)
dfv_M_dv_M_tilde = fv_M.diff(self.v_M_tilde)
expected = '2.591382*(1 + (-8.149*v_M_tilde - 0.374)**2)**(-1/2)'
assert PythonCodePrinter().doprint(dfv_M_dv_M_tilde) == expected
def test_lambdify(self):
fv_M = FiberForceVelocityDeGroote2016.with_defaults(self.v_M_tilde)
fv_M_callable = lambdify(self.v_M_tilde, fv_M)
assert fv_M_callable(0.0) == pytest.approx(1.002320622548512)
@pytest.mark.skipif(numpy is None, reason='NumPy not installed')
def test_lambdify_numpy(self):
fv_M = FiberForceVelocityDeGroote2016.with_defaults(self.v_M_tilde)
fv_M_callable = lambdify(self.v_M_tilde, fv_M, 'numpy')
v_M_tilde = numpy.array([-1.0, -0.5, 0.0, 0.5])
expected = numpy.array([
0.0120816781,
0.2438336294,
1.0023206225,
1.5850003903,
])
numpy.testing.assert_allclose(fv_M_callable(v_M_tilde), expected)
@pytest.mark.skipif(jax is None, reason='JAX not installed')
def test_lambdify_jax(self):
fv_M = FiberForceVelocityDeGroote2016.with_defaults(self.v_M_tilde)
fv_M_callable = jax.jit(lambdify(self.v_M_tilde, fv_M, 'jax'))
v_M_tilde = jax.numpy.array([-1.0, -0.5, 0.0, 0.5])
expected = jax.numpy.array([
0.0120816781,
0.2438336294,
1.0023206225,
1.5850003903,
])
numpy.testing.assert_allclose(fv_M_callable(v_M_tilde), expected)
class TestFiberForceVelocityInverseDeGroote2016:
@pytest.fixture(autouse=True)
def _tendon_force_length_inverse_arguments_fixture(self):
self.fv_M = Symbol('fv_M')
self.c0 = Symbol('c_0')
self.c1 = Symbol('c_1')
self.c2 = Symbol('c_2')
self.c3 = Symbol('c_3')
self.constants = (self.c0, self.c1, self.c2, self.c3)
@staticmethod
def test_class():
assert issubclass(FiberForceVelocityInverseDeGroote2016, Function)
assert issubclass(FiberForceVelocityInverseDeGroote2016, CharacteristicCurveFunction)
assert FiberForceVelocityInverseDeGroote2016.__name__ == 'FiberForceVelocityInverseDeGroote2016'
def test_instance(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016(self.fv_M, *self.constants)
assert isinstance(fv_M_inv, FiberForceVelocityInverseDeGroote2016)
assert str(fv_M_inv) == 'FiberForceVelocityInverseDeGroote2016(fv_M, c_0, c_1, c_2, c_3)'
def test_doit(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016(self.fv_M, *self.constants).doit()
assert fv_M_inv == (sinh((self.fv_M - self.c3)/self.c0) - self.c2)/self.c1
def test_doit_evaluate_false(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016(self.fv_M, *self.constants).doit(evaluate=False)
assert fv_M_inv == (sinh(UnevaluatedExpr(self.fv_M - self.c3)/self.c0) - self.c2)/self.c1
def test_with_defaults(self):
constants = (
Float('-0.318'),
Float('-8.149'),
Float('-0.374'),
Float('0.886'),
)
fv_M_inv_manual = FiberForceVelocityInverseDeGroote2016(self.fv_M, *constants)
fv_M_inv_constants = FiberForceVelocityInverseDeGroote2016.with_defaults(self.fv_M)
assert fv_M_inv_manual == fv_M_inv_constants
def test_differentiate_wrt_fv_M(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016(self.fv_M, *self.constants)
expected = cosh((self.fv_M - self.c3)/self.c0)/(self.c0*self.c1)
assert fv_M_inv.diff(self.fv_M) == expected
def test_differentiate_wrt_c0(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016(self.fv_M, *self.constants)
expected = (self.c3 - self.fv_M)*cosh((self.fv_M - self.c3)/self.c0)/(self.c0**2*self.c1)
assert fv_M_inv.diff(self.c0) == expected
def test_differentiate_wrt_c1(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016(self.fv_M, *self.constants)
expected = (self.c2 - sinh((self.fv_M - self.c3)/self.c0))/self.c1**2
assert fv_M_inv.diff(self.c1) == expected
def test_differentiate_wrt_c2(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016(self.fv_M, *self.constants)
expected = -1/self.c1
assert fv_M_inv.diff(self.c2) == expected
def test_differentiate_wrt_c3(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016(self.fv_M, *self.constants)
expected = -cosh((self.fv_M - self.c3)/self.c0)/(self.c0*self.c1)
assert fv_M_inv.diff(self.c3) == expected
def test_inverse(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016(self.fv_M, *self.constants)
assert fv_M_inv.inverse() is FiberForceVelocityDeGroote2016
def test_function_print_latex(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016(self.fv_M, *self.constants)
expected = r'\left( \operatorname{fv}^M \right)^{-1} \left( fv_{M} \right)'
assert LatexPrinter().doprint(fv_M_inv) == expected
def test_expression_print_latex(self):
fv_M = FiberForceVelocityInverseDeGroote2016(self.fv_M, *self.constants)
expected = r'\frac{- c_{2} + \sinh{\left(\frac{- c_{3} + fv_{M}}{c_{0}} \right)}}{c_{1}}'
assert LatexPrinter().doprint(fv_M.doit()) == expected
@pytest.mark.parametrize(
'code_printer, expected',
[
(
C89CodePrinter,
'(-0.12271444348999878*(0.374 - sinh(3.1446540880503142*(fv_M '
'- 0.88600000000000001))))',
),
(
C99CodePrinter,
'(-0.12271444348999878*(0.374 - sinh(3.1446540880503142*(fv_M '
'- 0.88600000000000001))))',
),
(
C11CodePrinter,
'(-0.12271444348999878*(0.374 - sinh(3.1446540880503142*(fv_M '
'- 0.88600000000000001))))',
),
(
CXX98CodePrinter,
'(-0.12271444348999878*(0.374 - sinh(3.1446540880503142*(fv_M '
'- 0.88600000000000001))))',
),
(
CXX11CodePrinter,
'(-0.12271444348999878*(0.374 - std::sinh(3.1446540880503142'
'*(fv_M - 0.88600000000000001))))',
),
(
CXX17CodePrinter,
'(-0.12271444348999878*(0.374 - std::sinh(3.1446540880503142'
'*(fv_M - 0.88600000000000001))))',
),
(
FCodePrinter,
' (-0.122714443489999d0*(0.374d0 - sinh(3.1446540880503142d0*(fv_M -\n'
' @ 0.886d0))))',
),
(
OctaveCodePrinter,
'(-0.122714443489999*(0.374 - sinh(3.14465408805031*(fv_M '
'- 0.886))))',
),
(
PythonCodePrinter,
'(-0.122714443489999*(0.374 - math.sinh(3.14465408805031*(fv_M '
'- 0.886))))',
),
(
NumPyPrinter,
'(-0.122714443489999*(0.374 - numpy.sinh(3.14465408805031'
'*(fv_M - 0.886))))',
),
(
SciPyPrinter,
'(-0.122714443489999*(0.374 - numpy.sinh(3.14465408805031'
'*(fv_M - 0.886))))',
),
(
CuPyPrinter,
'(-0.122714443489999*(0.374 - cupy.sinh(3.14465408805031*(fv_M '
'- 0.886))))',
),
(
JaxPrinter,
'(-0.122714443489999*(0.374 - jax.numpy.sinh(3.14465408805031'
'*(fv_M - 0.886))))',
),
(
MpmathPrinter,
'(-mpmath.mpf((0, 8842507551592581, -56, 53))*(mpmath.mpf((0, '
'3368692521273131, -53, 52)) - mpmath.sinh(mpmath.mpf((0, '
'7081131489576251, -51, 53))*(fv_M + mpmath.mpf((1, '
'7980378539700519, -53, 53))))))',
),
(
LambdaPrinter,
'(-0.122714443489999*(0.374 - math.sinh(3.14465408805031*(fv_M '
'- 0.886))))',
),
]
)
def test_print_code(self, code_printer, expected):
fv_M_inv = FiberForceVelocityInverseDeGroote2016.with_defaults(self.fv_M)
assert code_printer().doprint(fv_M_inv) == expected
def test_derivative_print_code(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016.with_defaults(self.fv_M)
dfv_M_inv_dfv_M = fv_M_inv.diff(self.fv_M)
expected = (
'0.385894476383644*math.cosh(3.14465408805031*fv_M '
'- 2.78616352201258)'
)
assert PythonCodePrinter().doprint(dfv_M_inv_dfv_M) == expected
def test_lambdify(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016.with_defaults(self.fv_M)
fv_M_inv_callable = lambdify(self.fv_M, fv_M_inv)
assert fv_M_inv_callable(1.0) == pytest.approx(-0.0009548832444487479)
@pytest.mark.skipif(numpy is None, reason='NumPy not installed')
def test_lambdify_numpy(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016.with_defaults(self.fv_M)
fv_M_inv_callable = lambdify(self.fv_M, fv_M_inv, 'numpy')
fv_M = numpy.array([0.8, 0.9, 1.0, 1.1, 1.2])
expected = numpy.array([
-0.0794881459,
-0.0404909338,
-0.0009548832,
0.043061991,
0.0959484397,
])
numpy.testing.assert_allclose(fv_M_inv_callable(fv_M), expected)
@pytest.mark.skipif(jax is None, reason='JAX not installed')
def test_lambdify_jax(self):
fv_M_inv = FiberForceVelocityInverseDeGroote2016.with_defaults(self.fv_M)
fv_M_inv_callable = jax.jit(lambdify(self.fv_M, fv_M_inv, 'jax'))
fv_M = jax.numpy.array([0.8, 0.9, 1.0, 1.1, 1.2])
expected = jax.numpy.array([
-0.0794881459,
-0.0404909338,
-0.0009548832,
0.043061991,
0.0959484397,
])
numpy.testing.assert_allclose(fv_M_inv_callable(fv_M), expected)
class TestCharacteristicCurveCollection:
@staticmethod
def test_valid_constructor():
curves = CharacteristicCurveCollection(
tendon_force_length=TendonForceLengthDeGroote2016,
tendon_force_length_inverse=TendonForceLengthInverseDeGroote2016,
fiber_force_length_passive=FiberForceLengthPassiveDeGroote2016,
fiber_force_length_passive_inverse=FiberForceLengthPassiveInverseDeGroote2016,
fiber_force_length_active=FiberForceLengthActiveDeGroote2016,
fiber_force_velocity=FiberForceVelocityDeGroote2016,
fiber_force_velocity_inverse=FiberForceVelocityInverseDeGroote2016,
)
assert curves.tendon_force_length is TendonForceLengthDeGroote2016
assert curves.tendon_force_length_inverse is TendonForceLengthInverseDeGroote2016
assert curves.fiber_force_length_passive is FiberForceLengthPassiveDeGroote2016
assert curves.fiber_force_length_passive_inverse is FiberForceLengthPassiveInverseDeGroote2016
assert curves.fiber_force_length_active is FiberForceLengthActiveDeGroote2016
assert curves.fiber_force_velocity is FiberForceVelocityDeGroote2016
assert curves.fiber_force_velocity_inverse is FiberForceVelocityInverseDeGroote2016
@staticmethod
@pytest.mark.skip(reason='kw_only dataclasses only valid in Python >3.10')
def test_invalid_constructor_keyword_only():
with pytest.raises(TypeError):
_ = CharacteristicCurveCollection(
TendonForceLengthDeGroote2016,
TendonForceLengthInverseDeGroote2016,
FiberForceLengthPassiveDeGroote2016,
FiberForceLengthPassiveInverseDeGroote2016,
FiberForceLengthActiveDeGroote2016,
FiberForceVelocityDeGroote2016,
FiberForceVelocityInverseDeGroote2016,
)
@staticmethod
@pytest.mark.parametrize(
'kwargs',
[
{'tendon_force_length': TendonForceLengthDeGroote2016},
{
'tendon_force_length': TendonForceLengthDeGroote2016,
'tendon_force_length_inverse': TendonForceLengthInverseDeGroote2016,
'fiber_force_length_passive': FiberForceLengthPassiveDeGroote2016,
'fiber_force_length_passive_inverse': FiberForceLengthPassiveInverseDeGroote2016,
'fiber_force_length_active': FiberForceLengthActiveDeGroote2016,
'fiber_force_velocity': FiberForceVelocityDeGroote2016,
'fiber_force_velocity_inverse': FiberForceVelocityInverseDeGroote2016,
'extra_kwarg': None,
},
]
)
def test_invalid_constructor_wrong_number_args(kwargs):
with pytest.raises(TypeError):
_ = CharacteristicCurveCollection(**kwargs)
@staticmethod
def test_instance_is_immutable():
curves = CharacteristicCurveCollection(
tendon_force_length=TendonForceLengthDeGroote2016,
tendon_force_length_inverse=TendonForceLengthInverseDeGroote2016,
fiber_force_length_passive=FiberForceLengthPassiveDeGroote2016,
fiber_force_length_passive_inverse=FiberForceLengthPassiveInverseDeGroote2016,
fiber_force_length_active=FiberForceLengthActiveDeGroote2016,
fiber_force_velocity=FiberForceVelocityDeGroote2016,
fiber_force_velocity_inverse=FiberForceVelocityInverseDeGroote2016,
)
with pytest.raises(AttributeError):
curves.tendon_force_length = None
with pytest.raises(AttributeError):
curves.tendon_force_length_inverse = None
with pytest.raises(AttributeError):
curves.fiber_force_length_passive = None
with pytest.raises(AttributeError):
curves.fiber_force_length_passive_inverse = None
with pytest.raises(AttributeError):
curves.fiber_force_length_active = None
with pytest.raises(AttributeError):
curves.fiber_force_velocity = None
with pytest.raises(AttributeError):
curves.fiber_force_velocity_inverse = None