Difference between revisions of "SymPy/Differential Equations"

From PrattWiki
Jump to navigation Jump to search
(Created page with " == Lessons Learned == * dsolve is good for up to two coupled ODEs. Once there are three or more...not so much (even if all the coefficients are ints or floats). Once ther...")
 
Line 1: Line 1:
  
 +
== Introduction ==
 +
This page focuses on using SymPy to find both the symbolic and the numeric solutions to differential equations obtained from electric circuits. The examples are available via a Google Drive at [https://drive.google.com/drive/folders/10Y1kzpu-DTTRwm1mYtdgTwpXF2zKpmoL?usp=sharing Basic Dsolve]. If you have the [https://workspace.google.com/marketplace/app/colaboratory/1014160490159 Google Colaboratory app] installed in your browser, you should be able to run the notebooks in your browser. If not, you can either install it or install a local program that can read notebook files such as Jupyter Notebooks, available with [https://www.anaconda.com/ Anaconda].  This page is based on [[SymPy/Simultaneous Equations]], which is likely a good place to start before going through this page!
  
 +
== Very Basic Example ==
 +
The example code below assumes you are either running code in a notebook of some kind or typing it into a console. If you want to follow along, the code is in the <code>dsolve_1</code> notebook in the [https://drive.google.com/drive/folders/10Y1kzpu-DTTRwm1mYtdgTwpXF2zKpmoL?usp=sharing Basic Dsolve] Google Drive folder.
 +
 +
Imagine you have the equation $$2\frac{dy(t)}{dt} + 3 y(t) = 4$$ with the initial condition $$y(0)=5$$, and you want to solve for $$y(t)$$. You can do this in SymPy as follows:
 +
 +
=== Initialization ===
 +
You will need to import sympy to use symbolic calculations. Pratt Pundit will generally give that module the nickname <code>sym</code>:
 +
<syntaxhighlight lang=python>
 +
import sympy as sym
 +
</syntaxhighlight>
 +
You will likely want your notebook or script to try to use $$\LaTeX$$ to render the results, so add:
 +
<syntaxhighlight lang=python>
 +
sym.init_printing(use_latex=True)
 +
</syntaxhighlight>
 +
as well.
 +
 +
=== Declare Variables and Functions ===
 +
You will need to let Python know what your variables and functions are.  For the example equation above, the unknown variable is $$t$$ and the unknown function is $$y$$; you can declare them with the following lines of code:
 +
<syntaxhighlight lang=python>
 +
t = sym.var('t')
 +
y = sym.Function('y')
 +
</syntaxhighlight>
 +
Note that the <code>Function</code> command starts with a capital F.
 +
 +
=== Define Equations ===
 +
To define a derivative in SymPy, use <code>sym.Derivative(FUN, VAR)</code>, where FUN is a function (with an argument, usually VAR) and VAR is the variable you are taking the derivative with respect to.  For instance, <code>sym.Derivative(y(t), t)</code> represents $$\frac{dy(t)}{dt}$$.  If you need to take a higher-order derivative, you can (a) append the independent variable to the argument list, (b) append the order of the derivative to the argument list, or (c) give a tuple with the independent argument and the order.  For example, to get $$\frac{d^2y(t)}{dt^2}$$, you can use <code>sym.Derivative(y(t), t, t)</code>, <code>sym.Derivative(y(t), t, 2)</code>, or <code>sym.Derivative(y(t), (t, 2))</code>.  See [https://docs.sympy.org/dev/guides/solving/solve-ode.html#defining-derivatives Defining Derivatives] at SymPy for further examples.
 +
 +
When it comes to solving things later, there are two different ways to define an equation:
 +
* If you have an expression that evaluates to other than zero, you can use sym.Eq(left, right) for that.  Given that we are trying to solve $$2\frac{dy(t)}{dt} + 3 y(t) = 4$$, you can write that in code as:
 +
<syntaxhighlight lang=python>
 +
eqn1 = sym.Eq(2 * sym.Derivative(y(t), t) + 3 * y(t), 4)
 +
</syntaxhighlight>
 +
* If the equation is equal to zero, you do not explicitly have to include the "=0" part; you can simply define a variable to hold on to the expression.  For instance, in this case, we can re-write the equation we are trying to solve as $$ax-d=0$$ and just define a variable to hold on to the left side:
 +
<syntaxhighlight lang=python>
 +
eqn1 = 2 * sym.Derivative(y(t), t) + 3 * y(t) - 4
 +
</syntaxhighlight>
 +
 +
=== Solve Equations ===
 +
There are two fundamentally different ways to solve one differential equation.  If you give the solver the equation and the function to solve for, it will return an equation with the solution in it:
 +
<syntaxhighlight lang=python>
 +
soln1 = sym.solve(eqn1, x)
 +
soln1
 +
</syntaxhighlight>
 +
will produce an equation that contains $$y(t)=\frac{C_1e^{-\frac{3t}{2}}}{3}+\frac{4}{3}$$.  On the other hand, if you give the solver a list with an equation in it and a list with the function in it, it will return a list with the equation in it:
 +
<syntaxhighlight lang=python>
 +
soln2 = sym.solve([eqn1], [y(t)])
 +
soln2
 +
</syntaxhighlight>
 +
will produce the list $$\left[ y(t)=\frac{C_1e^{-\frac{3t}{2}}}{3}+\frac{4}{3} \right]$$.
 +
This latter version is going to be much more useful if we are going to do anything else with the solution, so you should generally make sure to give <code>dsolve</code> two lists.  Note that unlike solving linear algebra equations, if you give a list of differential equations, you must also give a list with the functions.
 +
 +
=== Initial Conditions ===
 +
To incorporate initial conditions, you will give the <code>dsolve</code> command a dictionary of function values at particular times.  For example, to solve our sample equation with $$y(0)=5$$, you will include the initial condition by adding <code>ics={y(0)=5}</code> to the arguments.
 +
<syntaxhighlight lang=python>
 +
soln3 = sym.solve([eqn1], [y(t)], ics = {y(0): 5})
 +
soln3
 +
</syntaxhighlight>
 +
will produce $$\left[ y(t)=\frac{4}{3} + \frac{11e^{-\frac{3t}{2}}}{3} \right]$$
 +
 +
Note that the initial condition does not have to be at time 0; if you know that $$y(6)=7$$, you can use that as well:
 +
<syntaxhighlight lang=python>
 +
soln4 = sym.solve([eqn1], [y(t)], ics = {y(6): 7})
 +
soln4
 +
</syntaxhighlight>
 +
will produce $$\left[ y(t)=\frac{4}{3} + \frac{17e^9e^{-\frac{3t}{2}}}{3} \right]$$
  
 
== Lessons Learned ==
 
== Lessons Learned ==

Revision as of 12:52, 19 February 2023

Introduction

This page focuses on using SymPy to find both the symbolic and the numeric solutions to differential equations obtained from electric circuits. The examples are available via a Google Drive at Basic Dsolve. If you have the Google Colaboratory app installed in your browser, you should be able to run the notebooks in your browser. If not, you can either install it or install a local program that can read notebook files such as Jupyter Notebooks, available with Anaconda. This page is based on SymPy/Simultaneous Equations, which is likely a good place to start before going through this page!

Very Basic Example

The example code below assumes you are either running code in a notebook of some kind or typing it into a console. If you want to follow along, the code is in the dsolve_1 notebook in the Basic Dsolve Google Drive folder.

Imagine you have the equation $$2\frac{dy(t)}{dt} + 3 y(t) = 4$$ with the initial condition $$y(0)=5$$, and you want to solve for $$y(t)$$. You can do this in SymPy as follows:

Initialization

You will need to import sympy to use symbolic calculations. Pratt Pundit will generally give that module the nickname sym:

import sympy as sym

You will likely want your notebook or script to try to use $$\LaTeX$$ to render the results, so add:

sym.init_printing(use_latex=True)

as well.

Declare Variables and Functions

You will need to let Python know what your variables and functions are. For the example equation above, the unknown variable is $$t$$ and the unknown function is $$y$$; you can declare them with the following lines of code:

t = sym.var('t')
y = sym.Function('y')

Note that the Function command starts with a capital F.

Define Equations

To define a derivative in SymPy, use sym.Derivative(FUN, VAR), where FUN is a function (with an argument, usually VAR) and VAR is the variable you are taking the derivative with respect to. For instance, sym.Derivative(y(t), t) represents $$\frac{dy(t)}{dt}$$. If you need to take a higher-order derivative, you can (a) append the independent variable to the argument list, (b) append the order of the derivative to the argument list, or (c) give a tuple with the independent argument and the order. For example, to get $$\frac{d^2y(t)}{dt^2}$$, you can use sym.Derivative(y(t), t, t), sym.Derivative(y(t), t, 2), or sym.Derivative(y(t), (t, 2)). See Defining Derivatives at SymPy for further examples.

When it comes to solving things later, there are two different ways to define an equation:

  • If you have an expression that evaluates to other than zero, you can use sym.Eq(left, right) for that. Given that we are trying to solve $$2\frac{dy(t)}{dt} + 3 y(t) = 4$$, you can write that in code as:
eqn1 = sym.Eq(2 * sym.Derivative(y(t), t) + 3 * y(t), 4)
  • If the equation is equal to zero, you do not explicitly have to include the "=0" part; you can simply define a variable to hold on to the expression. For instance, in this case, we can re-write the equation we are trying to solve as $$ax-d=0$$ and just define a variable to hold on to the left side:
eqn1 = 2 * sym.Derivative(y(t), t) + 3 * y(t) - 4

Solve Equations

There are two fundamentally different ways to solve one differential equation. If you give the solver the equation and the function to solve for, it will return an equation with the solution in it:

soln1 = sym.solve(eqn1, x)
soln1

will produce an equation that contains $$y(t)=\frac{C_1e^{-\frac{3t}{2}}}{3}+\frac{4}{3}$$. On the other hand, if you give the solver a list with an equation in it and a list with the function in it, it will return a list with the equation in it:

soln2 = sym.solve([eqn1], [y(t)])
soln2

will produce the list $$\left[ y(t)=\frac{C_1e^{-\frac{3t}{2}}}{3}+\frac{4}{3} \right]$$. This latter version is going to be much more useful if we are going to do anything else with the solution, so you should generally make sure to give dsolve two lists. Note that unlike solving linear algebra equations, if you give a list of differential equations, you must also give a list with the functions.

Initial Conditions

To incorporate initial conditions, you will give the dsolve command a dictionary of function values at particular times. For example, to solve our sample equation with $$y(0)=5$$, you will include the initial condition by adding ics={y(0)=5} to the arguments.

soln3 = sym.solve([eqn1], [y(t)], ics = {y(0): 5})
soln3

will produce $$\left[ y(t)=\frac{4}{3} + \frac{11e^{-\frac{3t}{2}}}{3} \right]$$

Note that the initial condition does not have to be at time 0; if you know that $$y(6)=7$$, you can use that as well:

soln4 = sym.solve([eqn1], [y(t)], ics = {y(6): 7})
soln4

will produce $$\left[ y(t)=\frac{4}{3} + \frac{17e^9e^{-\frac{3t}{2}}}{3} \right]$$

Lessons Learned

  • dsolve is good for up to two coupled ODEs. Once there are three or more...not so much (even if all the coefficients are ints or floats). Once there are three or more (linear) coupled differential equations, consider going the Laplace route.
  • If your equations are a combination of differential equations a non-differential equations, dsolve expects all the differential equations to come first.

Example

See SymPy/Differential Equations/RC Example for a complete example