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
« 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
14def euler_equations(L, funcs=(), vars=()):
15 r"""
16 Find the Euler-Lagrange equations [1]_ for a given Lagrangian.
18 Parameters
19 ==========
21 L : Expr
22 The Lagrangian that should be a function of the functions listed
23 in the second argument and their derivatives.
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:
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)
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).
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.
41 vars : Symbol or an iterable of Symbols
42 The Symbols that are the independent variables of the functions.
44 Returns
45 =======
47 eqns : list of Eq
48 The list of differential equations, one for each function.
50 Examples
51 ========
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)]
65 References
66 ==========
68 .. [1] https://en.wikipedia.org/wiki/Euler%E2%80%93Lagrange_equation
70 """
72 funcs = tuple(funcs) if iterable(funcs) else (funcs,)
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)
81 vars = tuple(vars) if iterable(vars) else (vars,)
83 if not vars:
84 vars = funcs[0].args
85 else:
86 vars = tuple(sympify(var) for var in vars)
88 if not all(isinstance(v, Symbol) for v in vars):
89 raise TypeError('Variables are not symbols, got %s' % vars)
91 for f in funcs:
92 if not vars == f.args:
93 raise ValueError("Variables %s do not match args: %s" % (vars, f))
95 order = max([len(d.variables) for d in L.atoms(Derivative)
96 if d.expr in funcs] + [0])
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)
108 return eqns