# -*- coding: utf-8 -*-
"""
Spyder Editor
This is a temporary script file.
"""
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
g = 9.81 # [m/s**2]
N = 15 # number of time steps
# pump (project) requirements
Q = 10.0/3600 # flow design (best efficiency) point [m^3/s]
H = 12.0 # required pump head [m]
# calculated from other data but fixed in this case
d_1 = 30.0e-3 # outer streamline
d_2 = 60.0e-3 # outer streamline
omegaM = 300.0 # rotational speed 'magnitude' [rad/s]
omega = np.array([omegaM, 0.0, 0.0]) # rotational vector
# 'guessed' parameters
eps_c2 = np.pi/8 # angle of outlet cone (not very important)
b_2 = 6.0e-3 # outlet width (very important for efficienct vs. curve stability)
# specific energy
y = g*H
# circumferential speed at the outlet
u_2 = omegaM*d_2/2
# magnitude of absolute velocity at the outlet
# can be calculated right away using Euler's turbine equation
c_u2 = y/u_2
# meridian velocity at the outlet;
# calculate from flow and outlet area (cone frustum)
A_2 = np.pi*(d_1 + d_2)*b_2/2
c_m2 = Q/A_2
# magnitude of outlet velocity
c_2M = np.sqrt(c_m2**2 + c_u2**2)
# acceleration components:
# radial: get the difference in velocity from required head
c_r2 = c_m2 * np.cos(eps_c2) # radial velocity at the outlet
a_r = c_r2**2/(d_2 - d_1) # acceleration from c_r1 = 0 to c_r2, from d_1 to d_2
# solve the quadratic equation and take the bigger result
t = np.max(np.roots(np.array([a_r/2, c_r2, -(d_2-d_1)/2])))
# circumferential acceleration
a_u = c_u2/t
# axial component
A_1 = np.pi*d_1**2/4 # inlet surface
c_a1 = Q/A_1 # inlet axial velocity
c_a2 = c_2M*np.sin(eps_c2) # out ax. velocity
a_a = (c_a2 - c_a1)/t # axial acceleration
# calculate trajectory points
delta_t = t/N # time step
a_a0 = np.array([a_a, 0, 0])
a_r0 = np.array([0, a_r, 0])
a_u0 = np.array([0, 0, a_u])
a_0 = a_a + a_r + a_u # initial acceleration
p = np.array([0, d_1/2, 0]) # initial position
q = p # initial position for relative trajectory
c = np.array([c_a1, 0, 0]) # initial absolute ...
u = np.cross(omega, p) # ... circumferential
w = c - d_1/2 * omega # ... relative velocity
phi = 0 # initial angle
def rot_x(phi): # rotation around x-axis
return np.array([
[1, 0, 0],
[0, np.cos(phi), -np.sin(phi)],
[0, np.sin(phi), np.cos(phi)],
])
# trace of absolute velocity
trajectory = []
# trace of relative velocity
blade = []
# acceleration vectors
acceleration = []
for i in range(N):
# the movement in this timestep
p = p + c*delta_t # absolute
q = q + w*delta_t # relative
# move to next time step > next angle
phi += omegaM*delta_t
# rotate circumferential and radial acceleration, magnitude stays the same;
# axial acceleration stays the same
a_u = rot_x(phi).dot(a_u0)
a_r = rot_x(phi).dot(a_r0)
# the new acceleration
a = a_a + a_r + a_u
c += a*delta_t
u = np.cross(p, omega)
w = c - u
trajectory.append(p)
blade.append(q)
acceleration.append(np.linalg.norm(a))
# check if we're already at the edge
if np.sqrt(p[1]**2 + p[2]**2) > d_2/2:
print "ending at: " + str(i)
break# exit angle (beta_2)
# Kudos: https://stackoverflow.com/questions/2827393/
def unit_vector(vector):
""" Returns the unit vector of the vector. """
return vector / np.linalg.norm(vector)
def angle_between(v1, v2):
""" Returns the angle in radians between vectors 'v1' and 'v2'::
>>> angle_between((1, 0, 0), (0, 1, 0))
1.5707963267948966
>>> angle_between((1, 0, 0), (1, 0, 0))
0.0
>>> angle_between((1, 0, 0), (-1, 0, 0))
3.141592653589793
"""
v1_u = unit_vector(v1)
v2_u = unit_vector(v2)
return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))
# acc'rding to fusty books
# the exit angle doth be between 20 and 27 degrees
print 180-angle_between(w, u)*180/np.pi
###
### plot results
###
xs = []
ys = []
zs = []
Z = 5
plt.plot(acceleration)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# maximum values in all three directions;
# matplotlib can't set equal axes in 3D
vmax = 0
for angle in np.linspace(0, 2*np.pi, Z+1)[:-1]:
# plot absolute streamline
#xs = []
#ys = []
#zs = []
#for point in trajectory:
# p = rot_x(angle).dot(point)
# xs.append(p[0])
# ys.append(p[1])
# zs.append(p[2])
#ax.scatter(xs, ys, zs)
#plt.plot(ys, zs)
# plot relative streamline (blade)
xs = []
ys = []
zs = []
for point in blade:
p = rot_x(angle).dot(point)
vmax = max([vmax, p[0], p[1], p[2]])
xs.append(p[0])
ys.append(p[1])
zs.append(p[2])
ax.scatter(xs, ys, zs)
# just push the limits (once more)
ax.scatter([-vmax, vmax], [-vmax, vmax], [-vmax, vmax])
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')