Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/notebooks/chap22.ipynb
Views: 531
Modeling and Simulation in Python
Chapter 22
Copyright 2017 Allen Downey
Vectors
A Vector
object represents a vector quantity. In the context of mechanics, vector quantities include position, velocity, acceleration, and force, all of which might be in 2D or 3D.
You can define a Vector
object without units, but if it represents a physical quantity, you will often want to attach units to it.
I'll start by grabbing the units we'll need.
Here's a two dimensional Vector
in meters.
We can access the elements by name.
The magnitude is the length of the vector.
The angle is the number of radians between the vector and the positive x axis.
If we make another Vector
with the same units,
We can add Vector
objects like this
And subtract like this:
We can compute the Euclidean distance between two Vectors.
And the difference in angle
If we are given the magnitude and angle of a vector, what we have is the representation of the vector in polar coordinates.
We can use pol2cart
to convert from polar to Cartesian coordinates, and then use the Cartesian coordinates to make a Vector
object.
In this example, the Vector
we get should have the same components as A
.
Another way to represent the direction of A
is a unit vector, which is a vector with magnitude 1 that points in the same direction as A
. You can compute a unit vector by dividing a vector by its magnitude:
Or by using the hat
function, so named because unit vectors are conventionally decorated with a hat, like this: :
Exercise: Create a Vector
named a_grav
that represents acceleration due to gravity, with x component 0 and y component meters / second.
Degrees and radians
Pint provides units to represent degree and radians.
If you have an angle in degrees,
You can convert to radians.
If it's already in radians, to
does the right thing.
You can also convert from radians to degrees.
As an alterative, you can use np.deg2rad
, which works with Pint quantities, but it also works with simple numbers and NumPy arrays:
Exercise: Create a Vector
named a_force
that represents acceleration due to a force of 0.5 Newton applied to an object with mass 0.3 kilograms, in a direction 45 degrees up from the positive x-axis.
Add a_force
to a_grav
from the previous exercise. If that addition succeeds, that means that the units are compatible. Confirm that the total acceleration seems to make sense.
Baseball
Here's a Params
object that contains parameters for the flight of a baseball.
And here's the function that uses the Params
object to make a System
object.
Here's how we use it:
Here's a function that computes drag force using vectors:
We can test it like this.
Here's the slope function that computes acceleration due to gravity and drag.
Always test the slope function with the initial conditions.
We can use an event function to stop the simulation when the ball hits the ground:
Now we can call run_ode_solver
The final label tells us the flight time.
The final value of x
tells us the how far the ball landed from home plate:
Visualizing the results
The simplest way to visualize the results is to plot x and y as functions of time.
We can plot the velocities the same way.
The x velocity slows down due to drag.
The y velocity drops quickly while drag and gravity are in the same direction, then more slowly after the ball starts to fall.
Another way to visualize the results is to plot y versus x. The result is the trajectory of the ball through its plane of motion.
Animation
One of the best ways to visualize the results of a physical model is animation. If there are problems with the model, animation can make them apparent.
The ModSimPy library provides animate
, which takes as parameters a TimeSeries
and a draw function.
The draw function should take as parameters a State
object and the time. It should draw a single frame of the animation.
Inside the draw function, you almost always have to call set_xlim
and set_ylim
. Otherwise matplotlib
auto-scales the axes, which is usually not what you want.
Exercise: Delete the lines that set the x and y axes (or comment them out) and see what the animation does.
Under the hood
Vector
is a function that returns a ModSimVector
object.
A ModSimVector
is a specialized kind of Pint Quantity
.
There's one gotcha you might run into with Vectors and Quantities. If you multiply a ModSimVector
and a Quantity
, you get a ModSimVector
:
But if you multiply a Quantity
and a Vector
, you get a Quantity
:
With a ModSimVector
you can get the coordinates using dot notation, as well as mag
, mag2
, and angle
:
With a Quantity
, you can't. But you can use indexing to get the coordinates:
And you can use vector functions to get the magnitude and angle.
And often you can avoid the whole issue by doing the multiplication with the ModSimVector
on the left.
Exercises
Exercise: Run the simulation with and without air resistance. How wrong would we be if we ignored drag?
Exercise: The baseball stadium in Denver, Colorado is 1,580 meters above sea level, where the density of air is about 1.0 kg / meter. How much farther would a ball hit with the same velocity and launch angle travel?
Exercise: The model so far is based on the assumption that coefficient of drag does not depend on velocity, but in reality it does. The following figure, from Adair, The Physics of Baseball, shows coefficient of drag as a function of velocity.
I used an online graph digitizer to extract the data and save it in a CSV file. Here's how we can read it:
Modify the model to include the dependence of C_d
on velocity, and see how much it affects the results. Hint: use interpolate
.