euler.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. """
  2. This module implements a method to find
  3. Euler-Lagrange Equations for given Lagrangian.
  4. """
  5. from itertools import combinations_with_replacement
  6. from sympy.core.function import (Derivative, Function, diff)
  7. from sympy.core.relational import Eq
  8. from sympy.core.singleton import S
  9. from sympy.core.symbol import Symbol
  10. from sympy.core.sympify import sympify
  11. from sympy.utilities.iterables import iterable
  12. def euler_equations(L, funcs=(), vars=()):
  13. r"""
  14. Find the Euler-Lagrange equations [1]_ for a given Lagrangian.
  15. Parameters
  16. ==========
  17. L : Expr
  18. The Lagrangian that should be a function of the functions listed
  19. in the second argument and their derivatives.
  20. For example, in the case of two functions $f(x,y)$, $g(x,y)$ and
  21. two independent variables $x$, $y$ the Lagrangian has the form:
  22. .. math:: L\left(f(x,y),g(x,y),\frac{\partial f(x,y)}{\partial x},
  23. \frac{\partial f(x,y)}{\partial y},
  24. \frac{\partial g(x,y)}{\partial x},
  25. \frac{\partial g(x,y)}{\partial y},x,y\right)
  26. In many cases it is not necessary to provide anything, except the
  27. Lagrangian, it will be auto-detected (and an error raised if this
  28. cannot be done).
  29. funcs : Function or an iterable of Functions
  30. The functions that the Lagrangian depends on. The Euler equations
  31. are differential equations for each of these functions.
  32. vars : Symbol or an iterable of Symbols
  33. The Symbols that are the independent variables of the functions.
  34. Returns
  35. =======
  36. eqns : list of Eq
  37. The list of differential equations, one for each function.
  38. Examples
  39. ========
  40. >>> from sympy import euler_equations, Symbol, Function
  41. >>> x = Function('x')
  42. >>> t = Symbol('t')
  43. >>> L = (x(t).diff(t))**2/2 - x(t)**2/2
  44. >>> euler_equations(L, x(t), t)
  45. [Eq(-x(t) - Derivative(x(t), (t, 2)), 0)]
  46. >>> u = Function('u')
  47. >>> x = Symbol('x')
  48. >>> L = (u(t, x).diff(t))**2/2 - (u(t, x).diff(x))**2/2
  49. >>> euler_equations(L, u(t, x), [t, x])
  50. [Eq(-Derivative(u(t, x), (t, 2)) + Derivative(u(t, x), (x, 2)), 0)]
  51. References
  52. ==========
  53. .. [1] https://en.wikipedia.org/wiki/Euler%E2%80%93Lagrange_equation
  54. """
  55. funcs = tuple(funcs) if iterable(funcs) else (funcs,)
  56. if not funcs:
  57. funcs = tuple(L.atoms(Function))
  58. else:
  59. for f in funcs:
  60. if not isinstance(f, Function):
  61. raise TypeError('Function expected, got: %s' % f)
  62. vars = tuple(vars) if iterable(vars) else (vars,)
  63. if not vars:
  64. vars = funcs[0].args
  65. else:
  66. vars = tuple(sympify(var) for var in vars)
  67. if not all(isinstance(v, Symbol) for v in vars):
  68. raise TypeError('Variables are not symbols, got %s' % vars)
  69. for f in funcs:
  70. if not vars == f.args:
  71. raise ValueError("Variables %s do not match args: %s" % (vars, f))
  72. order = max([len(d.variables) for d in L.atoms(Derivative)
  73. if d.expr in funcs] + [0])
  74. eqns = []
  75. for f in funcs:
  76. eq = diff(L, f)
  77. for i in range(1, order + 1):
  78. for p in combinations_with_replacement(vars, i):
  79. eq = eq + S.NegativeOne**i*diff(L, diff(f, *p), *p)
  80. new_eq = Eq(eq, 0)
  81. if isinstance(new_eq, Eq):
  82. eqns.append(new_eq)
  83. return eqns