Coverage for /usr/lib/python3/dist-packages/sympy/calculus/euler.py: 24%

34 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1""" 

2This module implements a method to find 

3Euler-Lagrange Equations for given Lagrangian. 

4""" 

5from itertools import combinations_with_replacement 

6from sympy.core.function import (Derivative, Function, diff) 

7from sympy.core.relational import Eq 

8from sympy.core.singleton import S 

9from sympy.core.symbol import Symbol 

10from sympy.core.sympify import sympify 

11from sympy.utilities.iterables import iterable 

12 

13 

14def euler_equations(L, funcs=(), vars=()): 

15 r""" 

16 Find the Euler-Lagrange equations [1]_ for a given Lagrangian. 

17 

18 Parameters 

19 ========== 

20 

21 L : Expr 

22 The Lagrangian that should be a function of the functions listed 

23 in the second argument and their derivatives. 

24 

25 For example, in the case of two functions $f(x,y)$, $g(x,y)$ and 

26 two independent variables $x$, $y$ the Lagrangian has the form: 

27 

28 .. math:: L\left(f(x,y),g(x,y),\frac{\partial f(x,y)}{\partial x}, 

29 \frac{\partial f(x,y)}{\partial y}, 

30 \frac{\partial g(x,y)}{\partial x}, 

31 \frac{\partial g(x,y)}{\partial y},x,y\right) 

32 

33 In many cases it is not necessary to provide anything, except the 

34 Lagrangian, it will be auto-detected (and an error raised if this 

35 cannot be done). 

36 

37 funcs : Function or an iterable of Functions 

38 The functions that the Lagrangian depends on. The Euler equations 

39 are differential equations for each of these functions. 

40 

41 vars : Symbol or an iterable of Symbols 

42 The Symbols that are the independent variables of the functions. 

43 

44 Returns 

45 ======= 

46 

47 eqns : list of Eq 

48 The list of differential equations, one for each function. 

49 

50 Examples 

51 ======== 

52 

53 >>> from sympy import euler_equations, Symbol, Function 

54 >>> x = Function('x') 

55 >>> t = Symbol('t') 

56 >>> L = (x(t).diff(t))**2/2 - x(t)**2/2 

57 >>> euler_equations(L, x(t), t) 

58 [Eq(-x(t) - Derivative(x(t), (t, 2)), 0)] 

59 >>> u = Function('u') 

60 >>> x = Symbol('x') 

61 >>> L = (u(t, x).diff(t))**2/2 - (u(t, x).diff(x))**2/2 

62 >>> euler_equations(L, u(t, x), [t, x]) 

63 [Eq(-Derivative(u(t, x), (t, 2)) + Derivative(u(t, x), (x, 2)), 0)] 

64 

65 References 

66 ========== 

67 

68 .. [1] https://en.wikipedia.org/wiki/Euler%E2%80%93Lagrange_equation 

69 

70 """ 

71 

72 funcs = tuple(funcs) if iterable(funcs) else (funcs,) 

73 

74 if not funcs: 

75 funcs = tuple(L.atoms(Function)) 

76 else: 

77 for f in funcs: 

78 if not isinstance(f, Function): 

79 raise TypeError('Function expected, got: %s' % f) 

80 

81 vars = tuple(vars) if iterable(vars) else (vars,) 

82 

83 if not vars: 

84 vars = funcs[0].args 

85 else: 

86 vars = tuple(sympify(var) for var in vars) 

87 

88 if not all(isinstance(v, Symbol) for v in vars): 

89 raise TypeError('Variables are not symbols, got %s' % vars) 

90 

91 for f in funcs: 

92 if not vars == f.args: 

93 raise ValueError("Variables %s do not match args: %s" % (vars, f)) 

94 

95 order = max([len(d.variables) for d in L.atoms(Derivative) 

96 if d.expr in funcs] + [0]) 

97 

98 eqns = [] 

99 for f in funcs: 

100 eq = diff(L, f) 

101 for i in range(1, order + 1): 

102 for p in combinations_with_replacement(vars, i): 

103 eq = eq + S.NegativeOne**i*diff(L, diff(f, *p), *p) 

104 new_eq = Eq(eq, 0) 

105 if isinstance(new_eq, Eq): 

106 eqns.append(new_eq) 

107 

108 return eqns