CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download
Project: test
Views: 91872
1
# -*- coding: utf-8 -*-
2
"""
3
Created on Sat Jul 05 09:54:39 2014
4
5
@author: rlabbe
6
"""
7
8
from __future__ import division, print_function
9
import matplotlib.pyplot as plt
10
from scipy.integrate import ode
11
import math
12
import numpy as np
13
from numpy import random, radians, cos, sin
14
15
16
class BallTrajectory2D(object):
17
def __init__(self, x0, y0, velocity, theta_deg=0., g=9.8, noise=[0.0,0.0]):
18
theta = radians(theta_deg)
19
self.vx0 = velocity * cos(theta)
20
self.vy0 = velocity * sin(theta)
21
22
self.x0 = x0
23
self.y0 = y0
24
self.x = x
25
26
self.g = g
27
self.noise = noise
28
29
def position(self, t):
30
""" returns (x,y) tuple of ball position at time t"""
31
32
self.x = self.vx0*t + self.x0
33
self.y = -0.5*self.g*t**2 + self.vy0*t + self.y0
34
35
return (self.x +random.randn()*self.noise[0], self.y +random.randn()*self.noise[1])
36
37
38
39
class BallEuler(object):
40
def __init__(self, y=100., vel=10., omega=0):
41
self.x = 0.
42
self.y = y
43
omega = radians(omega)
44
self.vel = vel*np.cos(omega)
45
self.y_vel = vel*np.sin(omega)
46
47
48
49
def step (self, dt):
50
51
g = -9.8
52
53
54
self.x += self.vel*dt
55
self.y += self.y_vel*dt
56
57
self.y_vel += g*dt
58
59
#print self.x, self.y
60
61
62
63
def rk4(y, x, dx, f):
64
"""computes 4th order Runge-Kutta for dy/dx.
65
y is the initial value for y
66
x is the initial value for x
67
dx is the difference in x (e.g. the time step)
68
f is a callable function (y, x) that you supply to compute dy/dx for
69
the specified values.
70
"""
71
72
k1 = dx * f(y, x)
73
k2 = dx * f(y + 0.5*k1, x + 0.5*dx)
74
k3 = dx * f(y + 0.5*k2, x + 0.5*dx)
75
k4 = dx * f(y + k3, x + dx)
76
77
return y + (k1 + 2*k2 + 2*k3 + k4) / 6.
78
79
80
81
82
def fx(x,t):
83
return fx.vel
84
85
def fy(y,t):
86
return fy.vel - 9.8*t
87
88
89
class BallRungeKutta(object):
90
def __init__(self, x=0, y=100., vel=10., omega = 0.0):
91
self.x = x
92
self.y = y
93
self.t = 0
94
95
omega = math.radians(omega)
96
97
fx.vel = math.cos(omega) * vel
98
fy.vel = math.sin(omega) * vel
99
100
def step (self, dt):
101
self.x = rk4 (self.x, self.t, dt, fx)
102
self.y = rk4 (self.y, self.t, dt, fy)
103
self.t += dt
104
print(fx.vel)
105
return (self.x, self.y)
106
107
108
def ball_scipy(y0, vel, omega, dt):
109
110
vel_y = math.sin(math.radians(omega)) * vel
111
112
def f(t,y):
113
return vel_y-9.8*t
114
115
solver = ode(f).set_integrator('dopri5')
116
solver.set_initial_value(y0)
117
118
ys = [y0]
119
while brk.y >= 0:
120
t += dt
121
brk.step (dt)
122
123
ys.append(solver.integrate(t))
124
125
126
def RK4(f):
127
return lambda t, y, dt: (
128
lambda dy1: (
129
lambda dy2: (
130
lambda dy3: (
131
lambda dy4: (dy1 + 2*dy2 + 2*dy3 + dy4)/6
132
)( dt * f( t + dt , y + dy3 ) )
133
)( dt * f( t + dt/2, y + dy2/2 ) )
134
)( dt * f( t + dt/2, y + dy1/2 ) )
135
)( dt * f( t , y ) )
136
137
def theory(t): return (t**2 + 4)**2 /16
138
139
from math import sqrt
140
dy = RK4(lambda t, y: t*sqrt(y))
141
142
t, y, dt = 0., 1., .1
143
while t <= 10:
144
if abs(round(t) - t) < 1e-5:
145
print("y(%2.1f)\t= %4.6f \t error: %4.6g" % (t, y, abs(y - theory(t))))
146
147
t, y = t + dt, y + dy(t, y, dt)
148
149
t = 0.
150
y=1.
151
152
def test(y, t):
153
return t*sqrt(y)
154
155
while t <= 10:
156
if abs(round(t) - t) < 1e-5:
157
print("y(%2.1f)\t= %4.6f \t error: %4.6g" % (t, y, abs(y - theory(t))))
158
159
y = rk4(y, t, dt, test)
160
t += dt
161
162
if __name__ == "__main__":
163
1/0
164
165
dt = 1./30
166
y0 = 15.
167
vel = 100.
168
omega = 30.
169
vel_y = math.sin(math.radians(omega)) * vel
170
171
def f(t,y):
172
return vel_y-9.8*t
173
174
be = BallEuler (y=y0, vel=vel,omega=omega)
175
#be = BallTrajectory2D (x0=0, y0=y0, velocity=vel, theta_deg = omega)
176
ball_rk = BallRungeKutta (y=y0, vel=vel, omega=omega)
177
178
while be.y >= 0:
179
be.step (dt)
180
ball_rk.step(dt)
181
182
print (ball_rk.y - be.y)
183
184
'''
185
p1 = plt.scatter (be.x, be.y, color='red')
186
p2 = plt.scatter (ball_rk.x, ball_rk.y, color='blue', marker='v')
187
188
plt.legend([p1,p2], ['euler', 'runge kutta'])
189
'''
190