Applying Modified Euler to solve a Pendulum ODE in Python - python

So I am trying to implement some numerical methods into python and I am having some issues where all of my functions output more or less the same thing as the regular euler method. I assume this is because I am messing up in some way when I am implementing the method into code.
My pendulum is defined as this:
def func(y,t):
### Simplified the Function to remove friction since it cancelled out
x,v = y[:3],y[3:6]
grav = np.array([0., 0., -9.8 ])
lambd = (grav.dot(x)+v.dot(v))/x.dot(x)
return np.concatenate([v, grav - lambd*x] )
def dF_matrix(y):
n=y.size
dF=np.zeros((6,6))
xp=np.array([y[1],y[2],y[3]])[np.newaxis]
mass=1.
F1=0.
F2=0.
F3=-mass*9.8
F=np.array([F1,F2,F3])[np.newaxis]
phix=2.*y[0]
phiy=2.*y[4]
phiz=2.*y[5]
G=np.array([phix,phiy,phiz])[np.newaxis]
H=2.*np.eye(3)
lambd=(mass*np.dot(xp,np.dot(H,xp.T))+np.dot(F,G.T))/np.dot(G,G.T)
dF[0,3]=1
dF[1,4]=1
dF[2,5]=1
dF[3,0]=(y[0]*F1+2*lambd)/mass
dF[3,1]=(y[0]*F2)/mass
dF[3,2]=(y[0]*F3)/mass
dF[3,3]=phix*y[1]
dF[3,4]=phix*y[2]
dF[3,5]=phix*y[3]
dF[4,0]=(y[4]*F1)/mass
dF[4,1]=(y[4]*F2+2*lambd)/mass
dF[4,2]=(y[4]*F3)/mass
dF[4,3]=phiy*y[1]
dF[4,4]=phiy*y[2]
dF[4,5]=phiy*y[3]
dF[5,0]=(y[5]*F1)/mass
dF[5,1]=(y[5]*F2)/mass
dF[5,2]=(y[5]*F3+2*lambd)/mass
dF[5,3]=phiz*y[1]
dF[5,4]=phiz*y[2]
dF[5,5]=phiz*y[3]
return dF
The functions that I have made to integrate the ODE function are as follows (with help from others in previous a thread):
from scipy.integrate import odeint
from mpl_toolkits import mplot3d
import matplotlib.pyplot as plt
Forward Euler Method
def forward_Euler(function, y_matrix, time):
y = np.zeros((np.size(time), np.size(y_matrix)))
y[0, :] = y_matrix
for i in range(len(time) - 1):
dt = time[i + 1] - time[i]
y[i + 1, :] = y[i, :] + np.asarray(function(y[i, :], time[i])) * dt
return y
Modified Euler Method
ERROR STARTS HERE
The error I am getting is:
RuntimeWarning: invalid value encountered in double_scalars
lambd = (grav.dot(x)+v.dot(v))/x.dot(x)
def modified_Euler(function, y_matrix, time):
y = np.zeros((np.size(time), np.size(y_matrix))) # creates the matrix that we will fill
y[0, :] = y_matrix # sets the initial values of the matrix
for i in range(len(time) - 1): # apply the Euler
dt = time[i + 1] - time[i] # Step size
k1 = np.asarray(function(y[i, :], time[i])*dt)
k2 = np.asarray(function(y[i] + k1, time[i+1])*dt)
y[i + 1, :] = y[i, :] + .5 * (k1 + k2)
return y
Adams-Bashforth 2nd order
def Adams_Bash_2nd(function, y_matrix, time):
y = np.zeros((np.size(time), np.size(y_matrix)))
y[0, :] = y_matrix
dt = time[1] - time[0]
f_0 = function(y[0], time[0])
y[1] = y[0] + dt * f_0
y[1] = y[0] + 0.5*dt * (f_0+function(y[1], time[1]))
for i in range(len(time) - 1):
dt = time[i + 1] - time[i]
f_1 = function(y[i, :], time[i])
f_2 = function(f_1-1, time[i-1])
y[i + 1] = y[i] + 0.5 * dt * (3 * f_1 - f_2)
return y
Adams Bashforth Moulton Method
def Adams_Moulton(function, y_matrix, time):
y = np.zeros((np.size(time), np.size(y_matrix)))
y[0, :] = y_matrix
### predictor formula
for i in range(len(time) - 1):
dt = time[i + 1] - time[i]
f_1 = function(y[i, :], time[i])
f_2 = function(f_1-1, time[i-1])
y[i + 1, :] = y[i, :] + dt * f_1 + ((dt**2)/2) * f_2
### Corrector formula
for i in range(len(time) - 1):
dt = time[i + 1] - time[i]
k_1 = 9 * (function(y[i, :], time[i+1]))
k_2 = 19 * (function(y[i, :], time[i]))
k_3 = 5 * (function(y[i, :], time[i-1]))
k_4 = (function(y[i, :], time[i-2]))
y[i + 1, :] = y[i] + (dt/24) * (k_1 + k_2 - k_3 + k_4)
return y
RK4 step to use in next function
def RK4_step(f,y,t,dt, N=1):
dt /= N;
for k in range(N):
k1=f(y,t)*dt; k2=f(y+k1/2,t+dt/2)*dt; k3=f(y+k2/2,t+dt/2)*dt; k4=f(y+k3,t+dt)*dt;
y, t = y+(k1+2*(k2+k3)+k4)/6, t+dt
return y
Adams-Bashforth Moulton Method 4th order
def Adams_Moulton_4th(function, y_matrix, time):
y = np.zeros((np.size(time), np.size(y_matrix)))
y[0] = y_matrix
### bootstrap steps with 4th order one-step method
dt = time[4] - time[0]
y[4] = RK4_step(function, y[0], time[0], dt, N=4)
y[5] = RK4_step(function, y[4], time[4], dt, N=4)
y[1] = RK4_step(function, y[5], time[5], dt, N=4)
f_m2 = function(y[0], time[0])
f_m1 = function(y[4], time[4])
f_0 = function(y[5], time[5])
f_1 = function(y[1], time[1])
for i in range(3, len(time) - 1):
### predictor formula 4th order [ 55/24, -59/24, 37/24, -3/8 ]
f_m3, f_m2, f_m1, f_0 = f_m2, f_m1, f_0, f_1
y[i + 1] = y[i] + (dt / 24) * (55 * f_0 - 59 * f_m1 + 37 * f_m2 - 9 * f_m3)
f_1 = function(y[i + 1], time[i + 1])
### Corrector formula 4th order [ 3/8, 19/24, -5/24, 1/24 ]
y[i + 1] = y[i] + (dt / 24) * (9 * f_1 + 19 * f_0 - 5 * f_m1 + f_m2)
f_1 = function(y[i + 1], time[i + 1])
return y
I decided to program the way I am testing the functions into a with a function eliminating a good amount of lines from the previous iteration
# initial condition
y0 = np.array([0.0, 1.0, 0.0, 0.8, 0.0, 1.2])
def test_function(test_function):
print(test_function.__name__ + "...")
nt = 2500
time_start = process_time()
# time points
t = np.linspace(0, 25, nt)
# solve ODE
y1 = test_function(func, y0, t)
time_elapsed = (process_time() - time_start)
print('elapsed time', time_elapsed)
# compute residual:
r = y1[:, 0] ** 2 + y1[:, 1] ** 2 + y1[:, 2] ** 2 - 1
rmax1 = np.max(np.abs(r))
print('error', rmax1)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.plot3D(y1[:, 0], y1[:, 1], y1[:, 2], 'gray')
plt.show()
test_function(odeint)
test_function(forward_Euler)
test_function(modified_Euler)
test_function(Adams_Bash_2nd)
test_function(Adams_Moulton)
test_function(Adams_Moulton_4th)

The modified Euler method Does Not access points outside the step i -> i+1, there is no i-1 (note that in your source document the step, in the python code, not the formulas, is i-1 -> i with the loops starting at an appropriately increased index). It simply is (as you can find everywhere the mod. Euler or Heun method is discussed)
k1 = f(y[i] , t[i ])*dt;
k2 = f(y[i]+k1, t[i+1])*dt;
y[i+1] = y[i] + 0.5*(k1+k2);
In contrast, the Adams-Bashford method of order 2 and Adams-Moulton methods of order greater 2 Do access points from before the step i -> i+1, formally one has in AB2
y[i+1] = y[i] + 0.5*dt * (3*f[i] - f[i-1])
For a first implementation it would make sense to declare the f array the same way as the y array to implement this formula verbatim. It can be more economical to only keep a short array of f values that is shifted or rotated to give access to the last few f values.
Note that you need to initialize y[1] and f[1] with some other method of similar or higher order. Or if you want to have a "pure" run of the method, you need to initialize y[-1] and f[-1] and further back so that y[1] can be computed with the method formula.

Related

Function as argument raises TypeError ndarray

I have to analyse a mass with variable acceleration. The first function defines acceleration. The second return arrays for respectively place, speed and acceleration at time t. (t goes from 0-10 with increments of 0.1)
import numpy as np
import matplotlib.pyplot as plt
dt = 0.1
t0 = 0.0
t1 = 10.0
x0 = 0.0
v0 = 0.0
m = 5.0
t = np.linspace(0, 10, 101)
def versnelling(t):
return (0.7 * np.sin(3 * t)) / m
def numeriek(x0, v0, a_func, t):
x = np.zeros(len(t))
v = np.zeros(len(t))
a = np.zeros(len(t))
x[0] = x0
v[0] = v0
a[0] = a_func(t[0])
for i in range(len(t) - 1):
dt = t[i + 1] - t[i]
a[i + 1] = a0 + a_func(i)
v[i + 1] = v[i] + a[i] * dt
x[i + 1] = x[i] + v[i] * dt
return x, v, a
But when I call it:
numeriek(x0, v0, versnelling(t), t)
I get:
TypeError: 'numpy.ndarray' object is not callable
I tried just a 0 in a_function(), as well as a t
How do I fix it but most of all why does my code not work??
The parameter a_func seems to be a function, so when you call the numeriek it should be passed as versnelling and not versnelling(t) that is in fact a function invocation resulting in a value.
import numpy as np
import matplotlib.pyplot as plt
dt = 0.1
t0 = 0.0
t1 = 10.0
x0 = 0.0
v0 = 0.0
m = 5.0
t = np.linspace(0, 10, 101)
def versnelling(t):
return (0.7 * np.sin(3 * t)) / m
def numeriek(x0, v0, a_func, t):
x = np.zeros(len(t))
v = np.zeros(len(t))
a = np.zeros(len(t))
x[0] = x0
v[0] = v0
a[0] = a_func(t[0])
for i in range(len(t) - 1):
dt = t[i + 1] - t[i]
a[i + 1] = a[0] + a_func(i)
v[i + 1] = v[i] + a[i] * dt
x[i + 1] = x[i] + v[i] * dt
return x, v, a
if __name__ == "__main__":
print(numeriek(x0, v0, versnelling, t))

Error 'RuntimeWarning: invalid value encountered in double_scalars' upon addition and multiplication of numpy array elements

I am trying to write an algorithm for simulating the steady flow in a windtunnel around a rectangle. I based my code heavily on the beam.py code in the book 'A survey of computational physics' by Landau.
The code in the book is the following:
import matplotlib.pylab as p;
from mpl_toolkits.mplot3d import Axes3D ;
from numpy import *;
import numpy;
print( "Working, look for figure window after 100 iterations")
Nxmax = 70; Nymax = 20; IL = 10; H = 8; T = 8; h = 1.
u = zeros( (Nxmax + 1, Nymax + 1), float) # Stream
w = zeros( (Nxmax + 1, Nymax + 1), float) # Vorticity
V0 = 1.0; omega = 0.1; nu = 1.; iter = 0; R = V0*h/nu # Renold #
def borders(): # Method borders: init & B.C
for i in range(0, Nxmax + 1): # Initialize stream function
for j in range(0, Nymax + 1 ): # And vorticity
w[i, j] = 0.
u[i, j] = j * V0
for i in range(0, Nxmax + 1 ): # Fluid surface
u[i, Nymax] = u[i, Nymax - 1] + V0 * h
w[i, Nymax - 1] = 0.
for j in range(0, Nymax + 1 ):
u[1, j] = u[0, j]
w[0, j] = 0. # Inlet
for i in range(0, Nxmax + 1 ): # Centerline
if i <= IL and i>= IL + T:
u[i, 0] = 0.
w[i, 0] = 0.
for j in range(1, Nymax ): # Outlet
w[Nxmax, j] = w[Nxmax - 1, j]
u[Nxmax, j] = u[Nxmax - 1, j] # Boundary conditions
def beam(): # Method beam; BC for beam
for j in range (0, H + 1): # Beam sides
w[IL, j] = - 2 * u[IL - 1, j]/(h*h) # Front side
w[IL + T, j] = - 2 * u[IL + T + 1, j]/(h*h) # Back side
for i in range(IL, IL + T + 1): w[i, H - 1] = - 2 * u[i, H]/(h*h);
for i in range(IL, IL + T + 1 ):
for j in range(0, H + 1):
u[IL, j] = 0. # Front
u[IL+T, j] = 0. # Back
u[i, H] = 0; # top
def relax(): # Method to relax stream
beam() # Reset conditions at beam
for i in range(1, Nxmax): # Relax stream function
for j in range (1, Nymax):
r1 = omega*((u[i+1,j]+u[i-1,j]+u[i,j+1]+u[i,j-1] + h*h*w[i,j])*0.25-u[i,j])
u[i, j] += r1
for i in range(1, Nxmax): # Relax vorticity
for j in range(1, Nymax):
a1 = w[i+1, j] + w[i-1,j] + w[i,j+1] + w[i,j-1]
a2 = (u[i,j+1] - u[i,j-1])*(w[i+1,j] - w[i - 1, j])
a3 = (u[i+1,j] - u[i-1,j])*(w[i,j+1] - w[i, j - 1])
r2 = omega *( (a1 - (R/4.)*(a2 - a3) )/4.0 - w[i,j])
w[i, j] += r2
borders()
while (iter <= 100):
iter += 1
if iter%10 == 0: print (iter)
relax()
for i in range (0, Nxmax + 1):
for j in range(0, Nymax + 1 ): u[i, j] = u[i, j]/(V0*h) # V0h units
x = range(0, Nxmax - 1); y = range(0, Nymax - 1) # returns stream flow to plot
# for several iterations
X, Y = p.meshgrid(x, y)
def functz(u): # Return transform
Z = u[X, Y]
return Z
Z = functz(u) # here the function is called
fig = p.figure() # creates the figure
ax = Axes3D(fig) # plots the axis for the figure
ax.plot_wireframe(X, Y, Z, color = 'r') # surface of wireframe in red
ax.set_xlabel('X') # label the three axes
ax.set_ylabel('Y')
ax.set_zlabel('Stream Function')
p.show()
I discovered that if I increase the value of V_0 above 2 or 3 then I get a RuntimeWarning: invalid value encountered in double_scalars error when r1 and r2 are calculated.
I want to simulate with much larger velocities and I couldn't find a way to fix this problem. I don't really understand why it is even an error when there are no divisions by really small numbers, close to 0.
Can anyone help me out and spot the problem?
Thanks in advance
I tried to look up the answer but only found special scipy libraries for certain operators but in this code none of them could be used.

How to make Matplotlib Animation for a computer simulation of Earth, Moon and Asteroid (only animation part) in Python?

I'm trying to make a computer simulation for Earth, Moon and Asteroid as they orbit around the Sun.
The data r_earth, r_moon and the r_asteroid are already given (they are an array). The xlim and ylim are so big because I have to use real values from the universe, otherwise I wouldn't see anything on the animation.
import numpy as np
def RK4_step(y, t, f, dt): #for numerical part I decided to use RK4 method
k1 = dt * f(y, t)
k2 = dt * f(y + 0.5 * k1, t + 0.5 * dt)
k3 = dt * f(y + 0.5 * k2, t + 0.5 * dt)
k4 = dt * f(y + k3, t + dt)
return (t + dt, y + (k1 + 2. * (k2 + k3) + k4) / 6.)
def integrate_ode(y0, derivative_fn, step_fn, a, b, n):
dt = (b - a) / (n - 1)
t = a
y = np.array(y0)
res = [y]
for _ in range(1, n):
t, y = step_fn(y, t, derivative_fn, dt)
res.append(y)
return (np.linspace(a, b, n), np.array(res))
# np.array(res) is 2D array of dimensions (<time steps>, <um variables>) that holds the values for each time step.
# Initial parameters for body masses(Sun, Earth, Moon, Asteroid)
G = 6.674e-11
m_s = 1.989e30
m_e = 5.972e24
m_m = 7.346e22
m_a = 1e25
def derivative_fn(y, t): # vectors necessary for 2.Newton's Law
d1 = y[1] - y[0]
vec01 = d1 / np.linalg.norm(d1) ** 3
d2 = y[2] - y[0]
vec02 = d2 / np.linalg.norm(d2) ** 3
d3 = y[2] - y[1]
vec12 = d3 / np.linalg.norm(d3) ** 3
der = np.array([
y[3],
y[4],
y[5],
- G * m_s * y[0] / np.linalg.norm(y[0]) ** 3 + G * m_m * vec01 + G * m_a * vec02,
- G * m_s * y[1] / np.linalg.norm(y[1]) ** 3 - G * m_e * vec01 + G * m_a * vec12,
- G * m_s * y[2] / np.linalg.norm(y[2]) ** 3 - G * m_e * vec02 - G * m_m * vec12])
return der
# numerically computed data in the array form
# y = [r_e, r_m, r_a, v_e, v_m, v_a] -> 2D array of size (6, 2)
# the initial distances between the bodies,
# for Earth and Moon we compute it from 2nd Newton's Law (orbital velocity)
r_e0 = 1.519e11
v_e0 = np.sqrt(G * m_s / r_e0)
r_m0 = 1.521e11
v_m0 = np.sqrt(G * m_e / abs(r_m0 - r_e0))
r_a0 = 1e11
v_a0 = 31293 # m/s
y0 = np.array([[r_e0, 0.], [r_m0, 0.], [r_a0, 0.], [0., v_e0], [0., v_e0 + v_m0], [0., v_e0 + v_a0]])
# all the parameters are now in the array y0,
# the last two are velocities relative to the Earth
n = 10000
ts, ys = integrate_ode(y0, derivative_fn, RK4_step, 0., 5.154e7, n)
r_earth = ys[:, 0, :]
r_moon = ys[:, 1, :]
r_asteroid = ys[:, 2, :]
# Plotting
import matplotlib.pyplot as plt
plt.xlabel("x")
plt.ylabel("y")
plt.plot(r_earth[:, 0], r_earth[:, 1], label="Earth")
plt.plot(r_moon[:, 0], r_moon[:, 1], label="Moon")
plt.plot(r_asteroid[:, 0], r_asteroid[:, 1], label="Asteroid")
plt.show()
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
ax.set_xlim([-0.3e12, 0.3e12])
ax.set_ylim([-0.3e12, 0.3e12])
# xlim and ylim are so big because we wouldn't see the animation.
sun, = ax.plot(0., 0., 'oy', ms=20)
earth, = ax.plot(r_earth[0, 0], r_earth[0, 1], 'og', ms=10)
moon, = ax.plot(r_moon[0, 0], r_moon[0, 0], 'ob', ms=3)
asteroid, = ax.plot(r_asteroid[0, 0], r_asteroid[0, 0], 'ok', ms=1)
num_frames = 10000
frame_duration = n / num_frames
def animation_frame(frame):
index = int(frame_duration * frame)
earth.set_data(r_earth[index, 0], r_earth[index, 1])
moon.set_data(r_moon[index, 0] / r_earth[index, 0], r_moon[index, 1] / r_earth[index, 1])
asteroid.set_data(r_asteroid[index, 0] / r_earth[index, 0], r_asteroid[index, 1] / r_earth[index, 1])
return earth, moon, asteroid
animation = FuncAnimation(fig, func=animation_frame, frames=range(num_frames), interval=50)
plt.show()
When I start my code, the Moon is in the same position as Sun, both are static. The Earth is moving around the Sun very slowly and there is no Asteroid on the animation.
How to fix this?
I still want to use real data, but wish that animation would go 100x faster(but still smooth animation). How do I do that?

Overflow and Invalid Values encountered in double scalars - Nonlinear PDE Solving

I am seeking to find a finite difference solution to the 1D Nonlinear PDE
u_t = u_xx + u(u_x)^2
Code:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import math
'''
We explore three different numerical methods for solving the PDE, with solution u(x, t),
u_t = u_xx + u(u_x)^2
for (x, t) in (0, 1) . (0, 1/5)
u(x, 0) = 40 * x^2 * (1 - x) / 3
u(0, t) = u(1, t) = 0
'''
M = 30
dx = 1 / M
r = 0.25
dt = r * dx**2
N = math.floor(0.2 / dt)
x = np.linspace(0, 1, M + 1)
t = np.linspace(0, 0.2, N + 1)
U = np.zeros((M + 1, N + 1)) # Initial array for solution u(x, t)
U[:, 0] = 40 * x**2 * (1 - x) / 3 # Initial condition (: for the whole of that array)
U[0, :] = 0 # Boundary condition at x = 0
U[-1, :] = 0 # Boundary condition at x = 1 (-1 means end of the array)
'''
Explicit Scheme - Simple Forward Difference Scheme
'''
for q in range(0, N - 1):
for p in range(0, M - 1):
b = 1 / (1 - 2 * r)
C = r * U[p, q] * (U[p + 1, q] - U[p, q])**2
U[p, q + 1] = b * (U[p, q] + r * (U[p + 1, q + 1] + U[p - 1, q + 1]) - C)
T, X = np.meshgrid(t, x)
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(T, X, U)
#fig.colorbar(surf, shrink=0.5, aspect=5) # colour bar for reference
ax.set_xlabel('t')
ax.set_ylabel('x')
ax.set_zlabel('u(x, t)')
plt.tight_layout()
plt.savefig('FDExplSol.png', bbox_inches='tight')
plt.show()
The code I use produces the following error:
overflow encountered in double_scalars
C = r * U[p, q] * (U[p + 1, q] - U[p, q])**2
invalid value encountered in double_scalars
U[p, q + 1] = b * (U[p, q] + r * (U[p + 1, q + 1] + U[p - 1, q + 1]) - C)
invalid value encountered in double_scalars
C = r * U[p, q] * (U[p + 1, q] - U[p, q])**2
Z contains NaN values. This may result in rendering artifacts.
surf = ax.plot_surface(T, X, U)
I've looked up these errors and I assume that the square term generates values too small for the dtype. However when I try changing the dtype to account for a larger range of numbers (np.complex128) I get the same error.
The resulting plot obviously has most of its contents missing. So, my question is, what do I do?
Discretisation expression was incorrect.
Should be
for q in range(0, N - 1):
for p in range(0, M - 1):
U[p, q + 1] = r * (U[p + 1, q] - 2 * U[p, q] + U[p - 1, q]) + r * U[p, q] * (U[p + 1, q] - U[p, q])

Python code optimization using vectorizing iterative section

I am new to python and numpy there is this Second order PDE code which i want to vectorize to run in lesser time but since it uses function to fill each value in grid i m stuck.
def func(x, y):
return (-2 * np.pi ** 2) * np.sin(np.pi * x) * np.sin(np.pi * y)
def f1t(x, y):
return (np.sin(np.pi * x) * np.sin(np.pi * y))
def five_point(grid, i, j, h, grid_x, grid_y):
return ((grid[i + 1, j] + grid[i - 1, j] + grid[i, j + 1] + grid[i, j - 1]) / 4
- ((h ** 2) / 4) * func(grid_x[i, 0], grid_y[0, j]))
def five_point_fin_int(X=np.ones(1), Y=np.ones(1), n_x=32, K_max=1000,
tol=0.0001, tol_type="grid"):
import time;
t0 = time.clock()
h = 1 / n_x
X_max = int(X / h)
Y_max = int(Y / h)
grid_x, grid_y = np.mgrid[0:X + h:h, 0:Y + h:h]
grid_true = np.zeros((X_max + 1, Y_max + 1))
for i in range(1, X_max):
for j in range(1, Y_max):
grid_true[i, j] = f1t(grid_x[i, 0], grid_y[0, j])
grid = np.zeros((X_max + 1, Y_max + 1))
grid_err = np.zeros((X_max + 1, Y_max + 1))
count = 0
tol_max = False
while ((count < K_max) & (tol_max == False)):
count += 1
for i in range(1, X_max):
for j in range(1, Y_max):
grid[i, j] = five_point(grid, i, j, h, grid_x, grid_y)
grid_err[i, j] = (grid[i, j] - grid_true[i, j])
if (tol_type.lower() == "grid" ):
if (np.amax(abs(grid_err)) < tol):
tol_max = True
else:
if (abs(np.linalg.norm(grid) - np.linalg.norm(grid_true)) < tol):
tol_max = True
cpu_time = time.clock() - t0
In the end i print compute time since its nested for loops right now the time taken is a lot around 9 sec i would like to improvise on this.
numpy allows you to replace loops by vector calls. You can definitely do the following:
grid_true = np.zeros((X_max + 1, Y_max + 1))
grid_true[1:X_max,1:Y_max]=f1t(*np.meshgrid(grid_x[1:X_max,0], grid_y[0,1:Y_max]))
And you can also try the following:
grid = np.zeros((X_max + 1, Y_max + 1))
grid[1:-1, 1:-1] = five_point(grid, *np.meshgrid(np.arange(1,X_max), np.arange(1, Y_max)),
h, grid_x, grid_y)
However this is not pure "upstream" integration like the one you are doing, since you are essentialy calculating all the grid together in each step (your call!).
Probably a minimization routine could do better. There isn't much difference in performance between numpy and pure python for short loops or small vectors.

Categories

Resources