-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproject2(1).py
More file actions
278 lines (223 loc) · 7.39 KB
/
project2(1).py
File metadata and controls
278 lines (223 loc) · 7.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
"""
Your college id here:
Template code for project 2, contains 9 functions:
simulate1: complete function for part 1
part1q1a, part1q1b, part1q1c, part1q2: functions to be completed for part 1
dualfd1,fd2: complete functions for part 2
part2q1, part2q2: functions to be completed for part 2
"""
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt
#you may use numpy, scipy, and matplotlib as needed
#---------------------------- Code for Part 1 ----------------------------#
def simulate1(n,X0=-1,Nt=2000,tf=1000,g=1.0,mu=0.0,flag_display=False):
"""
Simulation code for part 1
Input:
n: number of ODEs
X0: initial condition if n-element numpy array. If X0 is an integer, the code will set
the initial condition (otherwise an array is expected).
Nt: number of time steps
tf: final time
g,mu: model parameters
flag_display: will generate a contour plot displaying results if True
Output:
t,x: numpy arrays containing times and simulation results
"""
def model(t, X, n, g, mu):
"""
Defines the system of ODEs
Input:
- t: time
- X: array of variables [x_0, x_1, ..., x_{n-1}]
- g, mu: scalar model parameters
- n: number of ODEs (size of the system)
Returns:
- dXdt: array of derivatives [dx_0/dt, dx_1/dt, ..., dx_{n-1}/dt]
"""
dXdt = np.zeros(n)
dXdt[0] = X[0]*(1-g*X[-2]-X[0]-g*X[1]+mu*X[-3])
dXdt[1] = X[1]*(1-g*X[-1]-X[1]-g*X[2])
dXdt[2:n-1] = X[2:n-1]*(1-g*X[0:n-3]-X[2:n-1]-g*X[3:n])
dXdt[-1] = X[-1]*(1-g*X[-3]-X[-1]-g*X[0])
return dXdt
# Parameters
t_span = (0, tf) # Time span for the integration
if type(X0)==int: #(modified from original version)
X0 = 1/(2*g+1)+0.001*np.random.rand(n) # Random initial conditions, modify if needed
# Solve the system
solution = solve_ivp(
fun=model,
t_span=t_span,
y0=X0,
args=(n, g, mu),
method='BDF',rtol=1e-10,atol=1e-10,
t_eval=np.linspace(t_span[0], t_span[1], Nt) # Times to evaluate the solution
)
t,x = solution.t,solution.y #in original version of code was inside if-block below
if flag_display:
# Plot the solution
plt.contour(t,np.arange(n),x,20)
plt.xlabel('i')
plt.ylabel('t')
return t,x
def part1q1a(n,g,mu,T):
"""Part 1, question 1 (a)
Use the variable inputs if/as needed.
Input:
n: number of ODEs
g,mu: model parameters
T: time at which perturbation energy ratio should be maximized
Output:
xbar: n-element array containing non-trivial equilibrium solution
xtilde0: n-element array corresponding to computed initial condition
eratio: computed maximum perturbation energy ratio
"""
#use/modify code below as needed:
xbar = np.zeros(n)
xtilde0 = np.zeros(n)
eratio = 0.0 #should be modified below
#add code here
return xbar,xtilde0,eratio
def part1q1b():
"""Part 1, question 1(b):
Add input/output if/as needed.
"""
#use/modify code below as needed:
n = 19
g = 1.2
mu = 2.5
T = 50
#add code here
return None #modify if needed
def part1q1c():
"""Part 1, question 1(c):
Add input/output if/as needed.
"""
#use/modify code below as needed:
n = 19
g = 2
mu = 0
#add code here
return None #modify if needed
def part1q2():
"""Part 1, question 2:
Add input/output if/as needed.
"""
#add code here
return None #modify if needed
#---------------------------- End code for Part 1 ----------------------------#
#---------------------------- Code for Part 2 ----------------------------#
def dualfd1(f):
"""
Code implementing implicit finite difference scheme for special case m=1
Implementation is not efficient.
Input:
f: n-element numpy array
Output:
df, d2f: computed 1st and 2nd derivatives
"""
#parameters, grid
n = f.size
h = 1/(n-1)
x = np.linspace(0,1,n)
#fd method coefficients
#interior points:
L1 = [7,h,16,0,7,-h]
L2 = [-9,-h,0,8*h,9,-h]
#boundary points:
L1b = [1,0,2,-h]
L2b = [0,h,-6,5*h]
L1b2 = [2,h,1,0]
L2b2 = [-6,-5*h,0,-h]
A = np.zeros((2*n,2*n))
#iterate filling a row of A each iteration
for i in range(n):
#rows 0 and N-1
if i==0:
#Set boundary eqn 1
A[0,0:4] = L1b
#Set boundary eqn 2
A[1,0:4] = L2b
elif i==n-1:
A[-2,-4:] = L1b2
A[-1,-4:] = L2b2
else:
#interior rows
#set equation 1
ind = 2*i
A[ind,ind-2:ind+4] = L1
#set equation 2
A[ind+1,ind-2:ind+4] = L2
#set up RHS
b = np.zeros(2*n)
c31,c22,cb11,cb21,cb31,cb12,cb22,cb32 = 15/h,24/h,-3.5/h,4/h,-0.5/h,9/h,-12/h,3/h
for i in range(n):
if i==0:
b[i] = cb11*f[0]+cb21*f[1]+cb31*f[2]
b[i+1] = cb12*f[0]+cb22*f[1]+cb32*f[2]
elif i==n-1:
b[-2] =-(cb11*f[-1]+cb21*f[-2]+cb31*f[-3])
b[-1] = -(cb12*f[-1]+cb22*f[-2]+cb32*f[-3])
else:
ind = 2*i
b[ind] = c31*(f[i+1]-f[i-1])
b[ind+1] = c22*(f[i-1]-2*f[i]+f[i+1])
out = np.linalg.solve(A,b)
df = out[::2]
d2f = out[1::2]
return df,d2f
def fd2(f):
"""
Computes the first and second derivatives with respect to x using second-order finite difference methods.
Input:
f: m x n array whose 1st and 2nd derivatives will be computed with respect to x
Output:
df, d2f: m x n arrays conaining 1st and 2nd derivatives of f with respect to x
"""
m,n = f.shape
h = 1/(n-1)
df = np.zeros_like(f)
d2f = np.zeros_like(f)
# First derivative
# Centered differences for the interior
df[:, 1:-1] = (f[:, 2:] - f[:, :-2]) / (2 * h)
# One-sided differences at the boundaries
df[:, 0] = (-3 * f[:, 0] + 4 * f[:, 1] - f[:, 2]) / (2 * h)
df[:, -1] = (3 * f[:, -1] - 4 * f[:, -2] + f[:, -3]) / (2 * h)
# Second derivative
# Centered differences for the interior
d2f[:, 1:-1] = (f[:, 2:] - 2 * f[:, 1:-1] + f[:, :-2]) / (h**2)
# One-sided differences at the boundaries
d2f[:, 0] = (2 * f[:, 0] - 5 * f[:, 1] + 4 * f[:, 2] - f[:, 3]) / (h**2)
d2f[:, -1] = (2 * f[:, -1] - 5 * f[:, -2] + 4 * f[:, -3] - f[:, -4]) / (h**2)
return df, d2f
def part2q1(f,h):
"""
Part 2, question 1
Input:
f: m x n array whose 1st and 2nd derivatives will be computed with respect to x
Output:
df, d2f: m x n arrays conaining 1st and 2nd derivatives of f with respect to x
computed with implicit fd scheme
"""
#use code below if/as needed
m,n = f.shape
h = 1/(n-1)
x = np.linspace(0,1,n)
y = np.linspace(0,1,m)
df = np.zeros_like(f) #modify as needed
d2f = np.zeros_like(f) #modify as needed
#Add code here
return df,d2f
def part2q2():
"""
Part 2, question 2
Add input/output as needed
"""
return None #modify as needed
#---------------------------- End code for Part 2 ----------------------------#
if __name__=='__main__':
x=0 #please do not remove
#Add code here to call functions used to generate the figures included in your report.