CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

CoCalc is a real-time collaborative commercial alternative to JupyterHub and Overleaf that provides Jupyter Notebooks, LaTeX documents, and SageMath.

| Download

Scientific Computing Midterm

Views: 888
1
import numpy as np
2
import pandas as pd
3
import matplotlib.pyplot as plt
4
from mpl_toolkits.mplot3d import Axes3D
5
#%matplotlib inline
6
7
class Attractor(object):
8
""" Here we begin by initializing our parameteres and store them as numpy arrays and/or setting
9
their default values. We also use these values to calculate the time increment (self.dt)."""
10
def __init__(self, s = 10.0, p = 28.0, b = 8.0/3.0, start = 0.0, end = 80.0, points = 10000):
11
inarr = np.array([s,p,b])
12
self.s = s
13
self.p = p
14
self.b = b
15
self.params = inarr
16
self.start = start
17
self.end = end
18
self.points = points
19
self.dt = ((self.end - self.start) / self.points)
20
self.t = np.linspace(self.start, self.end, self.points)
21
self.solution = pd.DataFrame()
22
23
def given(self, arr):
24
""" This method was created in hindsight to simplfy code further on in this Attractor class.
25
As we can see, this is where we work with our given set of differential equations and
26
convert them into terms more suitable for coding purposes and return the resulting numpy
27
array.
28
"""
29
x0,y0,z0 = arr
30
s,p,b = self.params
31
x = s * (y0 - x0)
32
y = x0 * (p - z0) - y0
33
z = x0 * y0 - b * z0
34
35
return np.array([x,y,z])
36
37
def euler(self, arr):
38
""" The euler method here takes a numpy array of length three as an argument, proceedes to
39
calculate the the first order Euler increment of the differential equations from our given
40
method, and returns the desired k1 value.
41
"""
42
43
k1 = arr + self.given(arr) * self.dt
44
45
return k1
46
47
def rk2(self, arr):
48
""" Here we have the rk2 method which in large is very similar to the euler method, however,
49
this method calculates and returns the second order Runge-Kutta increment.
50
"""
51
52
k1f = self.given(arr)
53
k2f = self.given(arr + k1f * self.dt / 2.0)
54
55
k2 = arr + k2f * self.dt
56
57
return k2
58
59
def rk4(self, arr):
60
""" Again, we have a near identical method here with the exception of how far we take the
61
incrementation. In rk4 we calculate and return the fourth order Runge-Kutta increment.
62
"""
63
64
k1f = self.given(arr)
65
k2f = self.given(arr + k1f * self.dt / 2.0)
66
k3f = self.given(arr + k2f * self.dt / 2.0)
67
k4f = self.given(arr + k3f * self.dt)
68
69
k4 = arr + self.dt / 6.0 * (k1f + 2 * k2f + 2 * k3f + k4f)
70
71
return k4
72
73
def evolve(self, r0 = np.array([0.1, 0.0, 0.0]), order = 4):
74
""" This method, evolve, takes a numpy array of length three and an integer as parameters.
75
The initial values (x0, y0, and z0) are given default values of 0.1, 0.0, and 0.0
76
respectively. The integer value order may take the quantities of 1, 2, or 4, defaulting
77
to 4, depending on which method is desired for incrementation. In this method we also
78
generate our pandas DataFrame and store it and return it as self.solution.
79
"""
80
if order == 1:
81
a = self.euler
82
elif order == 2:
83
a = self.rk2
84
elif order == 4:
85
a = self.rk4
86
else:
87
print "\n !!!Order was not 1, 2, or 4!!! \n"
88
return None
89
90
dd = {b: np.zeros(self.points) for b in 'txyz'}
91
self.solution = pd.DataFrame(dd)
92
xyz = r0
93
for i in range(self.points):
94
x, y, z = xyz
95
self.solution.loc[i] = [i * self.dt, x, y, z]
96
xyz = a(xyz)
97
98
return self.solution
99
100
def save(self, filename = None):
101
""" This is a very simple method to save our self.solution DataFrame to a CSV file on disk.
102
"""
103
filename = 'solution.csv'
104
self.solution.to_csv(filename)
105
106
def plotx(self):
107
""" This method simply labels axes and plots out t variable by our x(t) variable.
108
"""
109
plt.xlabel('t')
110
plt.ylabel('x(t)')
111
plt.plot(self.solution['t'], self.solution['x'])
112
plt.show()
113
114
def ploty(self):
115
""" This method simply labels axes and plots out t variable by our y(t) variable.
116
"""
117
plt.xlabel('t')
118
plt.ylabel('y(t)')
119
plt.plot(self.solution['t'], self.solution['y'])
120
plt.show()
121
122
def plotz(self):
123
""" This method simply labels axes and plots out t variable by our z(t) variable.
124
"""
125
plt.xlabel('t')
126
plt.ylabel('z(t)')
127
plt.plot(self.solution['t'], self.solution['z'])
128
plt.show()
129
130
def plotxy(self):
131
""" Now we keep on the same plotting track in this method except we plot our results
132
against one another. Namely, we're plotting x(t) vs y(t).
133
"""
134
plt.xlabel('x(t)')
135
plt.ylabel('y(t)')
136
plt.plot(self.solution['x'], self.solution['y'])
137
plt.show()
138
139
def plotyz(self):
140
""" Here we plot y(t) against z(t).
141
"""
142
plt.xlabel('y(t)')
143
plt.ylabel('z(t)')
144
plt.plot(self.solution['y'], self.solution['z'])
145
plt.show()
146
147
def plotzx(self):
148
""" This method plots x(t) by z(t).
149
"""
150
plt.xlabel('x(t)')
151
plt.ylabel('z(t)')
152
plt.plot(self.solution['x'], self.solution['z'])
153
plt.show()
154
155
def plot3d(self):
156
""" And finally we have the plotting method to give a 3D representation of all three,
157
x(t), y(t), and z(t), against eachother.
158
"""
159
td = plt.gca(projection='3d')
160
plt.plot(self.solution['x'], self.solution['y'], self.solution['z'])
161
plt.show()
162