solving the wave 1-d equation with python and animate - python
I'm trying to solve the 1-d wave equation, and I coding the program for numerical computing solutions and animating, saving data in the file. I don't know how to fix the error and finally get the working code.
u_tt = a**2 * u_xx + f(x,t)
It is necessary for the program to solve equations when entering both an additional function and with non-zero initial and boundary conditions, with graphic visualization and saving data to a file.
So I attach my code (Python 3.9), and error message:
import numpy as np
import math
import matplotlib.pyplot as plt
import os
import time
import glob
def sol(I, V, f, a, L, C, T, U_0, U_L, dt, user_func = None):
"""
solver for wave equation
u_tt = a**2*u_xx + f(x,t) (0,L) where u=0 for
x=0,L, for t in (0,T].
:param I:
:param V:
:param f:
:param a:
:param L:
:param C:
:param T:
:param U_0:
:param U_L:
:param dt:
:param user_func:
:return:
"""
nt = int(round(T / dt))
t = np.linspace(0, nt * dt, nt + 1) # array for time points
dx = dt * a / float(C)
nx = int(round(L / dx))
x = np.linspace(0, L, nx + 1) # array for coord points
q = a ** 2
C2 = (dt / dx) ** 2
dt2 = dt * dt
# --- checking f(x,t) ---
if f is None or f == 0:
f = lambda x, t: 0
# --- check the initial conds dU(x,0)/dt ---
if V is None or V == 0:
V = lambda x: 0
# boundary conds
if U_0 is not None:
if isinstance(U_0, (float, int)) and U_0 == 0:
U_0 = lambda t: 0
if U_L is not None:
if isinstance(U_L, (float, int)) and U_L == 0:
U_L = lambda t: 0
# --- allocate memory ---
u = np.zeros(nx + 1)
u_n = np.zeros(nx + 1)
u_nm = np.zeros(nx + 1)
# --- valid indexing check ---
Ix = range(0, nx + 1)
It = range(0, nt + 1)
# --- set the boundary conds ---
for i in range(0, nx + 1):
u_n[i] = I(x[i])
if user_func is not None:
user_func(u_n, x, t, 0)
# --- finite difference step ---
for i in Ix[1:-1]:
u[i] = u_n[i] + dt * V(x[i]) + 0.5 * C2 * (0.5 * (q[i] + q[i + 1]) * (u_n[i + 1] - u_n[i]) -
0.5 * (q[i] + q[i - 1]) * (u_n[i] - u_n[i - 1])) + 0.5 * dt2 * f(x[i], t[0])
i = Ix[0]
if U_0 is None:
# set the boundary conds (x=0: i-1 -> i+1 u[i-1]=u[i+1]
# where du/dn = 0, on x=L: i+1 -> i-1 u[i+1]=u[i-1])
ip1 = i + 1
im1 = ip1 # i-1 -> i+1
u[i] = u_n[i] + dt * V(x[i]) + \
0.5 * C2 * (0.5 * (q[i] + q[ip1]) * (u_n[ip1] - u_n[i]) - 0.5 * (q[i] + q[im1])
* (u_n[i] - u_n[im1])) + 0.5 * dt2 * f(x[i], t[0])
else:
u[i] = U_0(dt)
i = Ix[-1]
if U_L is None:
im1 = i - 1
ip1 = im1 # i+1 -> i-1
u[i] = u_n[i] + dt * V(x[i]) + \
0.5 * C2 * (0.5 * (q[i] + q[ip1]) * (u_n[ip1] - u_n[i]) - 0.5 * (q[i] + q[im1]) * (u_n[i] - u_n[im1])) + \
0.5 * dt2 * f(x[i], t[0])
else:
u[i] = U_L(dt)
if user_func is not None:
user_func(u, x, t, 1)
# update data
u_nm, u_n, u = u_n, u, u_nm
# --- time looping ---
for n in It[1:-1]:
# update all inner points
for i in Ix[1:-1]:
u[i] = - u_nm[i] + 2 * u_n[i] + \
C2 * (0.5 * (q[i] + q[i + 1]) * (u_n[i + 1] - u_n[i]) -
0.5 * (q[i] + q[i - 1]) * (u_n[i] - u_n[i - 1])) + dt2 * f(x[i], t[n])
# --- set boundary conds ---
i = Ix[0]
if U_0 is None:
# set the boundary conds
# x=0: i-1 -> i+1 u[i-1]=u[i+1] where du/dn=0
# x=L: i+1 -> i-1 u[i+1]=u[i-1] where du/dn=0
ip1 = i + 1
im1 = ip1
u[i] = - u_nm[i] + 2 * u_n[i] + \
C2 * (0.5 * (q[i] + q[ip1]) * (u_n[ip1] - u_n[i]) - 0.5 * (q[i] + q[im1]) * (u_n[i] - u_n[im1])) + \
dt2 * f(x[i], t[n])
else:
u[i] = U_0(t[n + 1])
i = Ix[-1]
if U_L is None:
im1 = i - 1
ip1 = im1
u[i] = - u_nm[i] + 2 * u_n[i] + \
C2 * (0.5 * (q[i] + q[ip1]) * (u_n[ip1] - u_n[i]) - 0.5 * (q[i] + q[im1]) * (u_n[i] - u_n[im1])) + \
dt2 * f(x[i], t[n])
else:
u[i] = U_L(t[n + 1])
if user_func is not None:
if user_func(u, x, t, n + 1):
break
u_nm, u_n, u = u_n, u, u_nm
return u, x, t
# --- here function for return functions ---
# return func(x)
def func(x):
"""
:param x:
:return:
"""
return # expression
# start simulate and animate or visualisation and savin the data from file
def simulate(
I, V, f, a, L, C, T, U_0, U_L, dt, # params
umin, umax, # amplitude
animate = True, # animate or not?
solver_func = sol, # call the solver
mode = 'plotter', # mode: plotting the graphic or saving to file
):
# code for visualization and simulate
...........
# start simulate
solver_func(I, V, f, a, L, C, T, U_0, U_L, dt, user_func)
return 0
def task( ):
'''
test tasking for solver and my problem
:return:
'''
I
L = 1
a = 1
C = 0.85
T = 1
dt = 0.05
U_0, U_L, V, f
umax = 2
umin = -umax
simulate(I, V, f, a, L, C, T, U_0, U_L, dt, umax, umin, animate = True, solver_func = sol, mode = 'plotter',)
if __name__ == '__main__':
task()
And I get the same error:
File "C:\\LR2-rep\wave_eq_1d.py", line 102, in sol
u[i] = u_n[i] + dt * V(x[i]) + 0.5 * C2 * (0.5 * (q[i] + q[i + 1]) * (u_n[i + 1] - u_n[i]) -
TypeError: 'int' object is not subscriptable
I understand the meaning of the error, but I do not understand how it can be fixed, and for almost two weeks I have not been able to write a program ... I ask for help with solving this problem! Thank you very much in advance!
Related
Invalid index to scalar variable error when trying to use scipy.optimize.curve_fit
I have a function with different parameters that I want to optimize to fit some existing data. The function runs fine on its own, but when I try to pass it through the scipy.optimize.curve_fit function, I get this error : IndexError: invalid index to scalar variable. I don't understand why the function would work on its own, and I would not get any errors. What can I do ? The original function used dictionnaries and I thought that might be the problem but I modified it and it still doesn't work. This is the function I'm using : def function_test(xy,X1,X2,X3,X4): precip = xy\[0\] potential_evap = xy\[1\] nUH1 = int(math.ceil(X4)) nUH2 = int(math.ceil(2.0*X4)) uh1_ordinates = [0] * nUH1 uh2_ordinates = [0] * nUH2 UH1 = [0] * nUH1 UH2 = [0] * nUH2 for t in range(1, nUH1 + 1): uh1_ordinates[t - 1] = s_curves1(t, X4) - s_curves1(t-1, X4) for t in range(1, nUH2 + 1): uh2_ordinates[t - 1] = s_curves2(t, X4) - s_curves2(t-1, X4) production_store = X1*0.60# S routing_store = X3*0.70# R qsim = [] for j in range(2191): if precip[j] > potential_evap[j]: net_evap = 0 scaled_net_precip = (precip[j] - potential_evap[j])/X1 if scaled_net_precip > 13: scaled_net_precip = 13. tanh_scaled_net_precip = tanh(scaled_net_precip) reservoir_production = (X1 * (1 - (production_store/X1)**2) * tanh_scaled_net_precip) / (1 + production_store/X1 * tanh_scaled_net_precip) routing_pattern = precip[j]-potential_evap[j]-reservoir_production else: scaled_net_evap = (potential_evap[j] - precip[j])/X1 if scaled_net_evap > 13: scaled_net_evap = 13. tanh_scaled_net_evap = tanh(scaled_net_evap) ps_div_x1 = (2 - production_store/X1) * tanh_scaled_net_evap net_evap = production_store * (ps_div_x1) / \ (1 + (1 - production_store/X1) * tanh_scaled_net_evap) reservoir_production = 0 routing_pattern = 0 production_store = production_store - net_evap + reservoir_production percolation = production_store / (1 + (production_store/2.25/X1)**4)**0.25 routing_pattern = routing_pattern + (production_store-percolation) production_store = percolation for i in range(0, len(UH1) - 1): UH1[i] = UH1[i+1] + uh1_ordinates[i]*routing_pattern UH1[-1] = uh1_ordinates[-1] * routing_pattern for j in range(0, len(UH2) - 1): UH2[j] = UH2[j+1] + uh2_ordinates[j]*routing_pattern UH2[-1] = uh2_ordinates[-1] * routing_pattern groundwater_exchange = X2 * (routing_store / X3)**3.5 routing_store = max(0, routing_store + UH1[0] * 0.9 + groundwater_exchange) R2 = routing_store / (1 + (routing_store / X3)**4)**0.25 QR = routing_store - R2 routing_store = R2 QD = max(0, UH2[0]*0.1+groundwater_exchange) Q = QR + QD qsim.append(Q) return qsim
Runge Kutta4 in python for complex system
I'm trying to solve a complex system where you can visualize it as some points/nodes where a spring-damper system is connected in between those nodes, each point carry the forces from all other connected springs and dampers in addition to the gravitational forces on them since each spring and damper have a specific mass. I'm using classes to make the grid and the initial conditions, but i'm not sure how exactly to calculate the new positions and accelerations using the runge kutta 4 this part is where runge kutta is defined rows = 5 columns = 6 class Runga_kutta4(): def __init__(self, node, u0, v0, t): self.u0 = u0 self.v0 = v0 self.t = t self.u = u = 0, 0 self.ux = u[0] self.uy = u[1] self.v = v = 0, 0 self.vx = v[0] self.vy = v[1] f = Forces(u0, u, v0, v) self.Node_Forces = f.nodeforces(node) self.dt = t[1] - t[0] results = self.calculation() return results # Returns the acceleration a def acceleration(self, Node_Forces): """ F = m *a a = F/m F_sys = F_externe - (F_damping + Springs) - F_g """ a_list = [] for (f, m) in zip(Node_Forces, Masses.Lattice_Mass()): ax = f[0]/m[0] ay = f[1]/m[1] a_list.append((ax, ay)) return a_list.reshape(5, 6) def calculation(self): for i in range(self.t.size - 1): # F at time step t / 2 f_t_05_x = (self.Node_Forces[0][i + 1] - self.Node_Forces[0][i]) / 2 + self.Node_Forces[0][i] f_t_05_y = (self.Node_Forces[1][i + 1] - self.Node_Forces[1][i]) / 2 + self.Node_Forces[1][i] u1x = self.ux[i] v1x = self.vx[i] u1y = self.uy[i] v1y = self.vy[i] a1x = self.acceleration(self.Node_Forces[0][i]) a1y = self.acceleration(self.Node_Forces[1][i]) u2x = self.ux[i] + v1x * self.dt / 2 v2x = self.vx[i] + a1x * self.dt / 2 u2y = self.uy[i] + v1y * self.dt / 2 v2y = self.vy[i] + a1y * self.dt / 2 a2x = self.acceleration(f_t_05_x) a2y = self.acceleration(f_t_05_y) u3x = self.ux[i] + v2x * self.dt / 2 v3x = self.vx[i] + a2x * self.dt / 2 u3y = self.uy[i] + v2y * self.dt / 2 v3y = self.vy[i] + a2y * self.dt / 2 a3x = self.acceleration(f_t_05_x) a3y = self.acceleration(f_t_05_y) u4x = self.ux[i] + v3x * self.dt v4x = self.vx[i] + a3x * self.dt u4y = self.uy[i] + v3y * self.dt v4y = self.vy[i] + a3y * self.dt a4x = self.acceleration(self.Node_Forces[0][i + 1]) a4y = self.acceleration(self.Node_Forces[1][i + 1]) self.ux[i + 1] = self.ux[i] + self.dt / 6 * (v1x + 2 * v2x + 2 * v3x + v4x) self.vx[i + 1] = self.vx[i] + self.dt / 6 * (a1x + 2 * a2x + 2 * a3x + a4x) self.uy[i + 1] = self.uy[i] + self.dt / 6 * (v1y + 2 * v2y + 2 * v3y + v4y) self.vy[i + 1] = self.vy[i] + self.dt / 6 * (a1y + 2 * a2y + 2 * a3y + a4y) self.u = (self.ux, self.uy) self.v = (self.vx, self.vy) return self.u, self.v l = Lattice(3) t0, te, dt = 0, 3, 0.001 # s t = np.linspace(t0, te, round((te-t0)/dt + 1)) for node in l.latticeNodes(): position0 = 0, 0 velocity0 = 0, 0 state0 = np.append(position0, velocity0) new_state = Runga_kutta4(node, position0, velocity0, t) visualise(l) photo of the system
Double sumption using python and the second argument depend on the first one
I have this relation to which I write the code using python to compute it , I am not sure if the code is right or not. Could you please give me any advice if it is true or how I can improve the code??, thanks import matplotlib.pyplot as plt import numpy as np from scipy.special import comb from scipy.constants import k from numpy import arange p12 = 1 # system initial state 12 w0 = 1 # system wn = 0 # wb/w0 bath U = 0.1 N = 50 n = (N/2) a =0.007 t = 1000# Time Z = 2**N * (np.cosh(U*wn/2))**N q12 = [] f11 = [] def Jrange(start, n, step): numelements = int((stop-start)/float(step)) for i in range(numelements+1): yield start + i*step def trange(tstart,tstop,tstep): tnumelements = int((tstop-tstart)/float(tstep)) for i in range(tnumelements+1): yield tstart + i*tstep for t in trange(tstart,tstop,tstep): roh2 = 0 roh12 = 0 roh1 = 0 roh11 = 0 for J in Jrange (0,stop,1) : Nj = (comb (N,(n+J))) - (comb (N,(n+J+1))) for m in arange (-J,J+1): r1 = np.sqrt (J*(J + 1) - m*(m + 1)) #r+ r2 = np.sqrt (J*(J + 1) - m*(m - 1)) #r- Omega1 = (w0 - wn) + (4 *a*(m + (1/2)))/(np.sqrt(N)) #Omeg+ gamma1 = np.sqrt( (Omega1**2 /4)+ (4*a**2 * r1**2)/N) # gamma+ Omega2 =-(w0 - wn) - (4 *a*(m - (1/2)))/(np.sqrt(N)) #Omega- gamma2 = np.sqrt( (Omega2**2 /4)+ (4*a**2 * r2**2)/N)#gamma- A1 = np.cos(gamma1*t) B1 = np.sin(gamma1*t) A2 = np.cos(gamma2*t) B2 = np.sin(gamma2*t) C = np.exp(-m*U*wn) H12 = C * (A1 - 1j*B1*Omega1/(2*gamma1)) * ((A2 +1j*B2*Omega2/(2*gamma2)) H2 = r2**2 * B2**2 * ((4*a**2)/ (gamma2**2 * N)) H1 = A1**2 + B1**2 *((Omega1**2)/ (4 * gamma1**2)) H11 = C * ((p11*H1) + (p22*H2)) roh11 = roh11+H11 roh12 = roh12 + H12 roh2= roh2 +roh12*Nj roh1 = roh1 + roh11*Nj Roh12 = roh2*D *p12*np.exp(1j*(w0-wn)*t) Roh11 = roh1 *D q12.append(Roh12) f11.append(Roh11)
ray caster, cast_ray function incorrectly accounts for obscured light
I am getting an error that says I am not accounting for obscured light and that my specular is getting added when the light is obscured. This is what the specular part that is being added onto is with x representing r, g, orb of my Color class: light.color.x * s.finish.specular * specIntense def in_shadow (sphere_list, sphere, ray_to_light, light): new_list = list() for s in sphere_list: if sphere != s: new_list.append(s) for s in new_list: if sphere_intersection_point(ray_to_light, s): x1 = ray_to_light.pt.x - light.pt.x y1 = ray_to_light.pt.y - light.pt.y z1 = ray_to_light.pt.z - light.pt.z dist1 = math.sqrt(x1 + y1 + z1) x2 = ray_to_light.pt.x - s.center.x y2 = ray_to_light.pt.y - s.center.y z2 = ray_to_light.pt.z - s.center.z dist2 = math.sqrt(x2 + y2 + z2) # distance to light, distance to sphere # check if distance to sphere < distance to light # if so return 0 if dist2 < dist1: return 0 return 1 def cast_ray(ray, sphere_list, color, light, point): # count = 0 dist = -1 cp = Color(1.0, 1.0, 1.0) for s in sphere_list: if sphere_intersection_point(ray, s): # count += 1 p = sphere_intersection_point(ray, s) vec = vector_from_to(s.center, p) N = normalize_vector(vec) norm_scaled = scale_vector(N, 0.01) pe = translate_point(p, norm_scaled) l = vector_from_to(pe, light.pt) l_dir = normalize_vector(l) dot = dot_vector(N, l_dir) r = Ray(pe, l_dir) dotNScaled = dot * 2 reflecVec = difference_vector(l_dir, scale_vector(N, dotNScaled)) V = vector_from_to(point, pe) Vdir = normalize_vector(V) spec = dot_vector(reflecVec, Vdir) m = in_shadow(sphere_list, s, r, light) if (dot <= 0): m = 0 x = (ray.pt.x - p.x) ** 2 y = (ray.pt.y - p.y) ** 2 z = (ray.pt.z - p.z) ** 2 curdist = math.sqrt(x + y + z) # print curdist if (dist < 0) or (dist > curdist): dist = curdist if (spec <= 0 ): r = ( s.color.r * s.finish.ambient * color.r ) \ + ( light.color.r * s.finish.diffuse * dot * s.color.r * m ) g = ( s.color.g * s.finish.ambient * color.g ) \ + (light.color.g * s.finish.diffuse * dot * s.color.g * m ) b = ( s.color.b * s.finish.ambient * color.b ) \ + (light.color.b * s.finish.diffuse * dot * s.color.b * m ) cp = Color(r, g, b) if ( spec >= 0 ): specIntense = spec ** (1/s.finish.roughness) print type(s.finish.diffuse) r = (s.color.r * s.finish.ambient * color.r) \ + (light.color.r * s.finish.diffuse * dot * s.color.r * m) \ + (light.color.r * s.finish.specular * specIntense) g = (s.color.g * s.finish.ambient * color.g) \ + (light.color.g * s.finish.diffuse * dot * s.color.g * m) \ + (light.color.g * s.finish.specular * specIntense) b = (s.color.b * s.finish.ambient * color.b) \ + (light.color.b * s.finish.diffuse * dot * s.color.b * m) \ + (light.color.b * s.finish.specular * specIntense) cp = Color(r, g, b) # if count > 1: # print 'intersects two!' return cp I think somewhere I am not accounting for the case where the sphere has another one in front of it therefore the specular part is being added to it when it shouldn't, creating this weird white light behind the first sphere that isn't supposed to be there. I'm sure there is a bug in this code somewhere but I cannot find it.
Numerical issue in scipy.ode.integrate solver
I am using ode solver to solve stiff problem (since odeint function could not able to solve it). But by this way also I have some warnings and my plot get saturate at some point. Here is image What should I do? Here is the list of warnings: DVODE-- Warning..internal T (=R1) and H (=R2) are such that in the machine, T + H = T on the next step (H = step size). solver will continue anyway In above, R1 = 0.3667661010318D+00 R2 = 0.1426374862242D-16 DVODE-- Warning..internal T (=R1) and H (=R2) are such that in the machine, T + H = T on the next step (H = step size). solver will continue anyway In above, R1 = 0.3667661010318D+00 R2 = 0.1426374862242D-16 DVODE-- Above warning has been issued I1 times. it will not be issued again for this problem In above message, I1 = 2 DVODE-- At current T (=R1), MXSTEP (=I1) steps taken on this call before reaching TOUT In above message, I1 = 500 In above message, R1 = 0.3667661010318D+00 My code: import numpy as np import matplotlib.pyplot as plt import scipy.integrate as si def func(): #arguments::: w = 1./3. xi = 2.86 phi1 = 1.645 phi2 = 2.* 1.202 gt = 10.**(-60) Lt = (1.202*gt)/np.pi Lin = 10.**-5 Lf = 0.49 dt = 0.0001 gin = gt*Lt/Lin xin = (-np.log((3. - (xi**2)*Lin)/(3. - (xi**2)*Lt)) + np.log(Lin/Lt))/4.0 uin = -(np.log(Lin/Lt))/2. state0 = [gin,xin,uin] print state0 def eq(L, state): g = state[0] x = state[1] u = state[2] N = (-2.*g/(6.*np.pi + 5.*g))*(18./(1. - 2.*L) + 5.*np.log(1.- 2.*L) - phi1 + 6. ) B = (-(2. - N)*L) - ((g/np.pi)* (5.*np.log(1.-2.*L) - phi2 + (5.*N/40.))) Eqs = np.zeros((3)) gdl = Eqs[0] = ((2.+N)*g)/B xdl = Eqs[1] = -(2./(3.*(1.+w)))* (1./(1.-(xi**2)*L/3.))*(1./B) udl = Eqs[2]= 1./B return Eqs ode = si.ode(eq) # BDF method suited to stiff systems of ODEs ode.set_integrator('vode',nsteps=500,method='bdf') ode.set_initial_value(state0,Lin) L = [] G = [] while ode.successful() and ode.t < Lf: ode.integrate(ode.t + dt) L.append(ode.t) G.append(ode.y) lam = np.vstack(L) g,x,u = np.vstack(G).T return g,x,u,lam r= func() L = r[3] g = r[0] lng = np.log10(g) x = r[1] u = r[2] w = 1./3. xi = 2.86 O_A = np.zeros(len(L)) q = np.zeros(len(L)) for i in np.arange(len(L)): O_A[i] = xi**2*L[i]/3. alpha = 2./ ((3.+3.*w) * (1.- (L[i]*xi**2)/3.) ) q[i] = 1./alpha - 1. n = np.zeros(len(L)) #eta(n) b = np.zeros(len(L)) for j in np.arange(len(L)): n[j] =(-2.*g[j]/(6.*np.pi + 5.*g[j]))*(18./(1. - 2.*L[j]) + 5.*np.log(1.- 2.*L[j]) - 1.645 + 6. ) b[j]= (-(2. - n[j])*L[j]) - ((g[j]/np.pi)* (5.*np.log(1.-2.*L[j]) - 2.* 1.202 + ((5.*n[j])/4.))) P = np.zeros(len(x)) for k in np.arange(len(x)): C = (((3. - (xi**2)*L[k])/g[k])**(3./4.)) * (((2.*L[k] + (u[k]*b[k]))*xi**2) + (n[k] * (3.- L[k]*xi**2)) ) P[k] = (np.exp(3.*x[k])) * (np.exp(4.*u[k])) * C plt.figure() plt.plot(L,P) plt.xlabel('Lambda ---->') plt.ylabel('P ----->') plt.title('lambda Vs P') plt.show()