AttributeError: 'IAPWS97' object has no attribute 'rho' - attributes

I am trying to run this loop; however, I am getting a no attribute error in the second portion of my code. Below is the entire code (sorry for the length). When I run the first case (PWR) the code executes normally as expected. However, when I run the second case (BWR) I receive the error even though it is the same exact statement from case one. Is there any fix or explanation for this? Thank you.
import numpy as np
import math
from iapws import IAPWS97
import matplotlib.pyplot as plt
case = int(input('Which case [1 (PWR) or 2 (BWR)]? '))
if case == 1: # PWR
H = 3.8 # m
He = 3.8 # m
Pitch = 1.25 * 10 ** (-2) # m
Gap_t = 0.00006 # m
D_fuel = 0.0082 # m
k_gap = 0.25 # W/m-K
k_c = 21.5 # W/m-K
k_fuel = 3.6 # W/m-K
T0 = float(278 + 273.15) # K
q0_prime = float(330 * 10 ** (2)) # W/m
P0 = 15 # MPa
MF = float(3460) # kg/m^2-s
D_rod = .0095 # m
R_rod = D_rod / 2
R_fuel = D_fuel / 2
R_gap = R_fuel + Gap_t
R_clad = R_rod
Clad_t = D_rod - D_fuel - Gap_t # m
h0_enthalpy = (IAPWS97(T=T0, P=P0).h) * 10 ** (3)
T_sat0 = IAPWS97(P=P0, x=0).T
g = 9.81 # m/s
# geometry properties
heated_p = math.pi * D_rod
wetted_p = math.pi * D_rod
A_f = (Pitch ** 2) - ((1 / 4) * math.pi * (D_rod ** 2))
D_H = (4 * A_f) / heated_p
# grid setup
grid_points = 100
dz = H / grid_points
z_array = np.arange(0, H, dz)
z_arrayplots = np.arange(0, H, dz)
q_HeatFluxList = []
# defining array of q'' values in list
for z in z_array:
heat_fluxA = (q0_prime / (math.pi * D_rod)) * math.sin(math.pi * (z / He))
q_HeatFluxList.append(heat_fluxA)
q_heat_flux = np.array(q_HeatFluxList)
q_prime = np.zeros(len(z_array))
for i in range(0, len(z_array)):
q_prime[i] = q0_prime * math.sin((np.pi * z_array[i]) / He)
# defining array of h values
h_enthalpy_list = []
h_enthalpy_prefactor = ((heated_p * q0_prime * H) / (A_f * MF * (math.pi ** 2) * D_rod))
for z in z_array:
h_enthalpy = (-h_enthalpy_prefactor * math.cos(math.pi * (z / He))) + h_enthalpy_prefactor + h0_enthalpy
h_enthalpy_list.append(h_enthalpy)
h_enthalpy_array_J = np.array(h_enthalpy_list)
h_enthalpy_array = h_enthalpy_array_J * 10 ** (-3)
P_array = np.zeros(len(z_array))
P_array[0] = P0
T_sat = np.zeros(len(z_array))
T_sat[0] = T_sat0
T_f_array = np.zeros(len(z_array))
T_f_array[0] = T0
Re = np.zeros(len(z_array))
Re_f = np.zeros(len(z_array))
Pr = np.zeros(len(z_array))
k_fluid = np.zeros(len(z_array))
x_array = np.zeros(len(z_array))
xe_array = np.zeros(len(z_array))
frictional = np.zeros(len(z_array))
gravitational = np.zeros(len(z_array))
compressibility = np.zeros(len(z_array))
# Pressure Loop PWR
dp = 0.001
for i in range(0, len(z_array) - 1):
rho_f = IAPWS97(P=P_array[i], x=0).rho
vf = IAPWS97(P=P_array[i], x=0).v
vg = IAPWS97(P=P_array[i], x=1).v
hf_enthalpy = IAPWS97(P=P_array[i], x=0).h
hg_enthalpy = IAPWS97(P=P_array[i], x=1).h
muf = (IAPWS97(P=P_array[i], x=0).mu) * 10 ** (-6)
mug = (IAPWS97(P=P_array[i], x=1).mu) * 10 ** (-6)
k_fluid[i] = IAPWS97(P=P_array[i], T=T_f_array[i]).k
Pr[i] = IAPWS97(P=P_array[i], h=h_enthalpy_array[i]).Liquid.Prandt
x_array[i] = 0
xe_array[i] = (h_enthalpy_array[i] - hf_enthalpy) / (hg_enthalpy - hf_enthalpy)
rho_m = 1 / ((x_array[i] * vg) + ((1 - x_array[i]) * vf))
mu_m = 1 / ((x_array[i] / mug) + ((1 - x_array[i]) / muf))
Re[i] = (MF * D_H) / (mu_m * 10 ** 6) # convert mu to Pa/s
f = 0.079 * (Re[i] ** -0.25) * (mu_m / muf)
Tau = (1 / 2) * f * ((MF ** 2) / rho_m)
Re_f[i] = Re[i]
vf_plus_dP = IAPWS97(P=P_array[i] + dp, x=0).v
vf_minus_dP = IAPWS97(P=P_array[i] - dp, x=0).v
ddP_vf = (vf_plus_dP - vf_minus_dP) / (2 * (dp * 10 ** 6))
frictional[i] = (Tau * wetted_p) / A_f
gravitational[i] = g * rho_f
compressibility[i] = (MF ** 2) * (ddP_vf)
dPdz_num = (frictional[i] + gravitational[i]) # Pa/m
dPdz_denom = 1 + compressibility[i] # Pa/m
dPdz = -dPdz_num / dPdz_denom # Pa/m
P_array[i + 1] = P_array[i] + ((dPdz * dz) * 10 ** (-6))
T_f_array[i + 1] = IAPWS97(P=P_array[i + 1], h=h_enthalpy_array[i + 1]).T
T_sat[i + 1] = IAPWS97(P=P_array[i + 1], x=0).T
# final calc for final value of quality and void fraction because loop stops before these
hf_final = IAPWS97(P=P_array[-1], x=0).h
hg_final = IAPWS97(P=P_array[-1], x=1).h
muf_final = (IAPWS97(P=P_array[-1], x=0).mu) * 10 ** (-6)
mug_final = (IAPWS97(P=P_array[-1], x=1).mu) * 10 ** (-6)
k_fluid[-1] = IAPWS97(P=P_array[-1], T=T_f_array[-1]).k
xe_array[-1] = (h_enthalpy_array[-1] - hf_final) / (hg_final - hf_final)
# fuel and clad temps
T_C_Outer = np.zeros(len(z_array))
mu_m_final = 1 / ((x_array[-1] / mug_final) + ((1 - x_array[-1]) / muf_final))
Re_f[-1] = (MF * D_H) / (muf_final * 10 ** 6)
Pr[-1] = IAPWS97(P=P_array[i], h=h_enthalpy_array[i]).Liquid.Prandt
h_HT = 0.023 * (Re_f[0] ** 0.8) * (Pr[0] ** 0.4) * (k_fluid[0] / D_H)
T_C_Outer[0] = (q_heat_flux[0] + (h_HT * T_f_array[0])) / h_HT
for i in range(0, len(z_array) - 1):
h_HT = 0.023 * (Re_f[i + 1] ** 0.8) * (Pr[i + 1] ** 0.4) * (k_fluid[i + 1] / D_H)
T_C_Outer[i + 1] = (q_heat_flux[i + 1] + (h_HT * T_f_array[i + 1])) / h_HT
q_triple_prime = (q_prime * 4) / (np.pi * (D_fuel ** 2))
T_C_Inner = np.zeros(len(z_array))
T_F_Outer = np.zeros(len(z_array))
T_F_Center = np.zeros(len(z_array))
for i in range(0, len(z_array)):
C1 = -((q0_prime * R_clad) / (k_c * heated_p)) * np.sin(np.pi * (z_array[i] / H))
C2 = T_C_Outer[i] - (C1 * np.log(R_clad))
T_C_Inner[i] = (C1 * np.log(R_gap)) + C2
C3 = (k_c / k_gap) * C1
C4 = T_C_Inner[i] - (C3 * np.log(R_gap))
T_F_Outer[i] = (C3 * np.log(R_fuel)) + C4
C6 = T_F_Outer[i] + ((q_triple_prime[i] * (R_fuel ** 2)) / (4 * k_fuel))
T_F_Center[i] = C6
CL_max = np.amax(T_F_Center)
index = np.where(T_F_Center == CL_max)
z_CL_max = z_array[index]
Clad_max = np.amax(T_C_Inner)
index = np.where(T_C_Inner == Clad_max)
z_Clad_max = z_array[index]
plt.figure(1)
plt.plot(T_C_Outer, z_arrayplots, label='Clad Outer Surface Temp')
plt.plot(T_C_Inner, z_arrayplots, label='Clad Inner Surface Temp')
plt.legend(loc='upper left')
plt.xlabel("Temperature [K]")
plt.ylabel("Height z [m]")
plt.savefig("TempClad.png", dpi=600)
plt.figure(2)
plt.plot(T_C_Outer, z_arrayplots, label='Clad Outer Surface Temp')
plt.plot(T_C_Inner, z_arrayplots, label='Clad Inner Surface Temp')
plt.plot(T_F_Outer, z_arrayplots, label='Fuel Outer Surface Temp')
plt.plot(T_F_Center, z_arrayplots, label='Fuel Centerline Temp')
plt.legend(loc='upper left')
plt.xlabel("Temperature [K]")
plt.ylabel("Height z [m]")
plt.savefig("TempFuelAndClad.png", dpi=600)
# radial calcs
T_array_A = [T_F_Center[25], T_F_Outer[25], T_C_Inner[25], T_C_Outer[25]]
T_array_B = [T_F_Center[49], T_F_Outer[49], T_C_Inner[49], T_C_Outer[49]]
T_array_C = [T_F_Center[53], T_F_Outer[53], T_C_Inner[53], T_C_Outer[53]]
r_array = [0, R_fuel, R_gap, R_clad]
plt.figure(3)
plt.plot(r_array, T_array_A, label='z = -H/4 = -0.9 m')
plt.plot(r_array, T_array_B, label='z = 0 m')
plt.plot(r_array, T_array_C, '--', label='z = zmax = 0.108 m')
plt.legend(loc='upper left')
plt.ylabel("Temperature [K]")
plt.xlabel("Radius r [m]")
plt.savefig("TempRadial.png", dpi=600)
# critical heat flux and DNBR
P_array_DNBR = np.delete(P_array, 0)
q_heat_flux_DNBR = np.delete(q_heat_flux, 0)
z_arrayplots_DNBR = np.delete(z_arrayplots, 0)
G_Mlbs = MF * (((2.20462 * 10 ** (-6)) * 3600) / 10.7639)
q_heat_flux_MBtu = q_heat_flux[1:] * 3.41 * (1 / 1000000) * (1 / 10.7639)
P_c = 22.064 # https://nuclearstreet.com/nuclear-power-plants/w/nuclear_power_plants/features-of-pressurized-water-reactors
P_crit = P_array_DNBR / P_c
P1 = 0.5328
P2 = 0.1212
P3 = 1.6151
P4 = 1.4066
P5 = -0.3040
P6 = 0.4843
P7 = -0.3285
P8 = -2.0749
A = P1 * (P_crit ** P2) * (G_Mlbs ** (P5 + (P7 * P_crit)))
C = P3 * (P_crit ** P4) * (G_Mlbs ** (P6 + (P8 * P_crit)))
q_crit_heat_flux_MBtu = (A - xe_array[0]) / (C + ((xe_array[1:] - xe_array[0]) / q_heat_flux_MBtu))
q_crit_heat_flux = q_crit_heat_flux_MBtu * (1 / 3.41) * 1000000 * 10.7639
DNBR = q_crit_heat_flux / q_heat_flux_DNBR
plt.figure(4)
plt.plot(DNBR, z_arrayplots_DNBR)
plt.xlabel("Departure from Nucleate Boiling Ratio")
plt.ylabel("Height z [m]")
plt.savefig("DNBR.png", dpi=600)
plt.figure(5)
plt.plot(P_array, z_arrayplots)
plt.xlabel('Pressure [MPa]')
plt.ylabel('Height z [m]')
plt.savefig("Pressure.png", dpi=600)
plt.figure(6)
plt.plot(T_f_array, z_arrayplots)
plt.xlabel('Temperature [K]')
plt.ylabel('Height z [m]')
plt.savefig("TempBulk.png", dpi=600)
plt.figure(7)
plt.plot(T_F_Outer, z_arrayplots, label='Fuel Outer Surface Temp')
plt.plot(T_F_Center, z_arrayplots, label='Fuel Centerline Temp')
plt.legend(loc='upper left')
plt.xlabel("Temperature [K]")
plt.ylabel("Height z [m]")
plt.savefig("TempFuel.png", dpi=600)
tempdifference = T_C_Outer - T_f_array
print("Max clad vs bulk difference is " + str(np.amax(tempdifference)) + " K")
print("Max coolant temp is " + str(np.amax(T_f_array)) + " K")
print("Min coolant temp is " + str(np.amin(T_f_array)) + " K")
print("Max clad inner temp is " + str(np.amax(T_C_Inner)) + " K")
print("Max clad outer temp is " + str(np.amax(T_C_Outer)) + " K")
print("min clad outer temp is " + str(np.amin(T_C_Outer)) + " K")
print("Max fuel temp is " + str(np.amax(T_F_Center)) + " K")
print("Max fuel outer temp is " + str(np.amax(T_F_Outer)) + " K")
print("Min fuel outer temp is " + str(np.amin(T_F_Outer)) + " K")
print("Max centerline temp occurs at z = " + str(z_CL_max) + "m")
print("Max clad temp occurs at z = " + str(z_Clad_max) + "m")
MDNBR = np.amin(DNBR)
print("MDNBR is " + str(MDNBR))
plt.show()
if case == 2: # BWR
H = 3.8 # m
He = 3.8 # m
Pitch = 1.63 * 10 ** (-2) # m
Gap_t = 0.0001 # m
D_fuel = 0.0104 # m
k_gap = 0.25 # W/m-K
k_c = 21.5 # W/m-K
k_fuel = 3.6 # W/m-K
T0 = float(274 + 273.15) # K
q0_prime = float(410 * 10 ** (2)) # W/m
P0 = 7.5 # MPa
MF = float(2290) # kg/m^2-s
D_rod = .0123 # m
R_rod = D_rod / 2
R_fuel = D_fuel / 2
R_gap = R_fuel + Gap_t
R_clad = R_rod
Clad_t = D_rod - D_fuel - Gap_t # m
h0_enthalpy = (IAPWS97(T=T0, P=P0).h) * 10 ** (3)
T_sat0 = IAPWS97(P=P0, x=0).T
g = 9.81 # m/s
# geometry properties
heated_p = math.pi * D_rod
wetted_p = math.pi * D_rod
A_f = (Pitch ** 2) - ((1 / 4) * math.pi * (D_rod ** 2))
D_H = (4 * A_f) / heated_p
# grid setup
grid_points = 100
dz = H / grid_points
z_array = np.arange(0, H, dz)
z_arrayplots = np.arange(-H / 2, H / 2, dz)
q_HeatFluxList = []
# defining array of q'' values in list
for z in z_array:
heat_fluxA = (q0_prime / (math.pi * D_rod)) * math.sin(math.pi * (z / He))
q_HeatFluxList.append(heat_fluxA)
q_heat_flux = np.array(q_HeatFluxList)
q_prime = np.zeros(len(z_array))
for i in range(0, len(z_array)):
q_prime[i] = q0_prime * math.sin((np.pi * z_array[i]) / He)
# defining array of h values
h_enthalpy_list = []
h_enthalpy_prefactor = ((heated_p * q0_prime * H) / (A_f * MF * (math.pi ** 2) * D_rod))
for z in z_array:
h_enthalpy = (-h_enthalpy_prefactor * math.cos(math.pi * (z / He))) + h_enthalpy_prefactor + h0_enthalpy
h_enthalpy_list.append(h_enthalpy)
h_enthalpy_array_J = np.array(h_enthalpy_list)
h_enthalpy_array = h_enthalpy_array_J * 10 ** (-3)
P_array = np.zeros(len(z_array))
P_array[0] = P0
T_sat = np.zeros(len(z_array))
T_sat[0] = T_sat0
T_f_array = np.zeros(len(z_array))
T_f_array[0] = T0
Re = np.zeros(len(z_array))
Re_f = np.zeros(len(z_array))
Pr = np.zeros(len(z_array))
k_fluid = np.zeros(len(z_array))
x_array = np.zeros(len(z_array))
xe_array = np.zeros(len(z_array))
dxe_array = np.zeros(len(z_array))
frictional = np.zeros(len(z_array))
gravitational = np.zeros(len(z_array))
compressibility = np.zeros(len(z_array))
alpha_array = np.zeros(len(z_array))
# Pressure Loop BWR
dp = 0.001
for i in range(0, len(z_array) - 1):
rho_f = IAPWS97(P=P_array[i], x=0).rho
rho_m = IAPWS97(P=P_array[i], x=xe_array[i]).rho
vf = IAPWS97(P=P_array[i], x=0).v
vg = IAPWS97(P=P_array[i], x=1).v
vfg = vg - vf
hf_enthalpy = IAPWS97(P=P_array[i], x=0).h
hg_enthalpy = IAPWS97(P=P_array[i], x=1).h
hfg = hg_enthalpy - hf_enthalpy
hfg_sat = IAPWS97(P=P0, x=1).h - IAPWS97(P=P0, x=0).h
# vf = IAPWS97(P=P_array[i], x=0).v
# vg_sat = IAPWS97(P=P_array[i], x=1).v
hf_in = IAPWS97(P=P0, T=T0).h
muf = (IAPWS97(P=P_array[i], x=0).mu) * 10 ** (-6)
mum = (IAPWS97(P=P_array[i], x=xe_array[i]).mu) * 10 ** (-6)
mug = (IAPWS97(P=P_array[i], x=1).mu) * 10 ** (-6)
k_fluid[i] = IAPWS97(P=P_array[i], T=T_f_array[i]).k
Pr[i] = IAPWS97(P=P_array[i], h=h_enthalpy_array[i]).Liquid.Prandt
xe_in = (hf_in - hf_enthalpy) / (hfg)
vf_sat = IAPWS97(P=P_array[i], x=xe_array[i])
# vapor quality
if xe_array[i] <= 0: # single phase
Re1p = MF * D_rod / muf
f1p = 0.316 * Re1p ** (-.25)
dp = -(.5 * f1p * MF * 2 * heated_p / (rho_f * A_f) + g / rho_f) * dz
x_array[i] = 0
dxe_array[i] = q0_prime * np.sin(np.pi * z_array[i] / H) / (MF * A_f * hfg_sat) * dz
xe_array = xe_array[i - 1] + dxe_array[i]
# P_array[i]=P[i-1]+dp1p
elif xe_array[i] > 0 and xe_array[i] < 1: # 2 phase
Re2p = MF * D_rod / mum
f2p = 0.046 * Re2p ** (-.2) * (muf / mum ** (-.2))
dp2p = (-MF ** 2 * vfg * dxe_array[i] + .5 * f2p * MF ** 2 * heated_p / (rho_m * A_f) + g * rho_m) * dz
xe_array[i] = (h_enthalpy_array[i] - hf_enthalpy) / (hg_enthalpy - hf_enthalpy)
# Void Fraction
if xe_array[i] <= 0:
alpha_array[0]
elif xe_array[i] > 0 and xe_array[i] < 1:
x_array[i] = xe_array[i]
vfg_sat = vg - vf
rho_m = (vf_sat + vfg_sat * x_array) ** (-1)
rhof = 1 / vf
rhog = 1 / vg
void = (rho_m - rhof) / (rhog - rhof)
alpha_array[void]
print("Void fraction is " + str(np.amax(alpha_array)))
if xe_array[i] <= 0:
alpha_array[0]
elif xe_array[i] > 0 and xe_array[i] < 1:
x_array[i] = xe_array[i]
vfg_sat = vg - vf
rho_m = (vf_sat + vfg_sat * x_array) ** (-1)
rhof = 1 / vf
rhog = 1 / vg
void = (rho_m - rhof) / (rhog - rhof)
alpha_array[void]
print("Void fraction is " + str(np.amax(alpha_array)))
rho_m = 1 / ((x_array[i] * vg) + ((1 - x_array[i]) * vf))
mu_m = 1 / ((x_array[i] / mug) + ((1 - x_array[i]) / muf))
Re[i] = (MF * D_H) / (mu_m * 10 ** 6) # convert mu to Pa/s
f = 0.079 * (Re[i] ** -0.25) * (mu_m / muf)
Tau = (1 / 2) * f * ((MF ** 2) / rho_m)
Re_f[i] = Re[i]
vf_plus_dP = IAPWS97(P=P_array[i] + dp, x=xe_array[i]).v
vf_minus_dP = IAPWS97(P=P_array[i] - dp, x=xe_array[i]).v
ddP_vf = (vf_plus_dP - vf_minus_dP) / (2 * (dp * 10 ** 6))
frictional[i] = (Tau * wetted_p) / A_f
gravitational[i] = g * rho_f
compressibility[i] = (MF ** 2) * (ddP_vf)
dPdz_num = (frictional[i] + gravitational[i]) # Pa/m
dPdz_denom = 1 + compressibility[i] # Pa/m
dPdz = -dPdz_num / dPdz_denom # Pa/m
P_array[i + 1] = P_array[i] + ((dPdz * dz) * 10 ** (-6))
T_f_array[i + 1] = IAPWS97(P=P_array[i + 1], h=h_enthalpy_array[i + 1]).T
T_sat[i + 1] = IAPWS97(P=P_array[i + 1], x=0).T
# final calc for final value of quality and void fraction because loop stops before these
hf_final = IAPWS97(P=P_array[-1], x=0).h
hg_final = IAPWS97(P=P_array[-1], x=1).h
muf_final = (IAPWS97(P=P_array[-1], x=0).mu) * 10 ** (-6)
mug_final = (IAPWS97(P=P_array[-1], x=1).mu) * 10 ** (-6)
k_fluid[-1] = IAPWS97(P=P_array[-1], T=T_f_array[-1]).k
xe_array[-1] = (h_enthalpy_array[-1] - hf_final) / (hg_final - hf_final)
# fuel and clad temps
T_C_Outer = np.zeros(len(z_array))
mu_m_final = 1 / ((x_array[-1] / mug_final) + ((1 - x_array[-1]) / muf_final))
Re_f[-1] = (MF * D_H) / (muf_final * 10 ** 6)
Pr[-1] = IAPWS97(P=P_array[i], h=h_enthalpy_array[i]).Liquid.Prandt
h_HT = 0.023 * (Re_f[0] ** 0.8) * (Pr[0] ** 0.4) * (k_fluid[0] / D_H)
T_C_Outer[0] = (q_heat_flux[0] + (h_HT * T_f_array[0])) / h_HT
for i in range(0, len(z_array) - 1):
h_HT = 0.023 * (Re_f[i + 1] ** 0.8) * (Pr[i + 1] ** 0.4) * (k_fluid[i + 1] / D_H)
T_C_Outer[i + 1] = (q_heat_flux[i + 1] + (h_HT * T_f_array[i + 1])) / h_HT
q_triple_prime = (q_prime * 4) / (np.pi * (D_fuel ** 2))
T_C_Inner = np.zeros(len(z_array))
T_F_Outer = np.zeros(len(z_array))
T_F_Center = np.zeros(len(z_array))
for i in range(0, len(z_array)):
C1 = -((q0_prime * R_clad) / (k_c * heated_p)) * np.sin(np.pi * (z_array[i] / H))
C2 = T_C_Outer[i] - (C1 * np.log(R_clad))
T_C_Inner[i] = (C1 * np.log(R_gap)) + C2
C3 = (k_c / k_gap) * C1
C4 = T_C_Inner[i] - (C3 * np.log(R_gap))
T_F_Outer[i] = (C3 * np.log(R_fuel)) + C4
C6 = T_F_Outer[i] + ((q_triple_prime[i] * (R_fuel ** 2)) / (4 * k_fuel))
T_F_Center[i] = C6
CL_max = np.amax(T_F_Center)
index = np.where(T_F_Center == CL_max)
z_CL_max = z_array[index]
plt.figure(1)
plt.plot(T_C_Outer, z_arrayplots, label='Clad Outer Surface Temp')
plt.plot(T_C_Inner, z_arrayplots, label='Clad Inner Surface Temp')
plt.legend(loc='upper left')
plt.xlabel("Temperature [K]")
plt.ylabel("Height z [m]")
plt.savefig("TempCladBWR.png", dpi=600)
plt.figure(2)
plt.plot(T_C_Outer, z_arrayplots, label='Clad Outer Surface Temp')
plt.plot(T_C_Inner, z_arrayplots, label='Clad Inner Surface Temp')
plt.plot(T_F_Outer, z_arrayplots, label='Fuel Outer Surface Temp')
plt.plot(T_F_Center, z_arrayplots, label='Fuel Centerline Temp')
plt.legend(loc='upper left')
plt.xlabel("Temperature [K]")
plt.ylabel("Height z [m]")
plt.savefig("TempFuelAndCladBWR.png", dpi=600)
# radial calcs
T_array_A = [T_F_Center[25], T_F_Outer[25], T_C_Inner[25], T_C_Outer[25]]
T_array_B = [T_F_Center[49], T_F_Outer[49], T_C_Inner[49], T_C_Outer[49]]
T_array_C = [T_F_Center[53], T_F_Outer[53], T_C_Inner[53], T_C_Outer[53]]
r_array = [0, R_fuel, R_gap, R_clad]
plt.figure(3)
plt.plot(r_array, T_array_A, label='z = -H/4 = -0.9 m')
plt.plot(r_array, T_array_B, label='z = 0 m')
plt.plot(r_array, T_array_C, '--', label='z = zmax = 0.108 m')
plt.legend(loc='upper left')
plt.ylabel("Temperature [K]")
plt.xlabel("Radius r [m]")
plt.savefig("TempRadialBWR.png", dpi=600)
# critical heat flux and DNBR
P_array_DNBR = np.delete(P_array, 0)
q_heat_flux_DNBR = np.delete(q_heat_flux, 0)
z_arrayplots_DNBR = np.delete(z_arrayplots, 0)
G_Mlbs = MF * (((2.20462 * 10 ** (-6)) * 3600) / 10.7639)
q_heat_flux_MBtu = q_heat_flux[1:] * 3.41 * (1 / 1000000) * (1 / 10.7639)
P_c = 22.064 # https://nuclearstreet.com/nuclear-power-plants/w/nuclear_power_plants/features-of-pressurized-water-reactors
P_crit = P_array_DNBR / P_c
P1 = 0.5328
P2 = 0.1212
P3 = 1.6151
P4 = 1.4066
P5 = -0.3040
P6 = 0.4843
P7 = -0.3285
P8 = -2.0749
A = P1 * (P_crit ** P2) * (G_Mlbs ** (P5 + (P7 * P_crit)))
C = P3 * (P_crit ** P4) * (G_Mlbs ** (P6 + (P8 * P_crit)))
q_crit_heat_flux_MBtu = (A - xe_array[0]) / (C + ((xe_array[1:] - xe_array[0]) / q_heat_flux_MBtu))
q_crit_heat_flux = q_crit_heat_flux_MBtu * (1 / 3.41) * 1000000 * 10.7639
DNBR = q_crit_heat_flux / q_heat_flux_DNBR
plt.figure(4)
plt.plot(DNBR, z_arrayplots_DNBR)
plt.xlabel("Onset of Nucleate Boiling Ratio")
plt.ylabel("Height z [m]")
plt.title("Onset of Nucleate Boiling Ratio versus Height")
plt.savefig("ONBR.png", dpi=600)
plt.figure(5)
plt.plot(P_array, z_arrayplots)
plt.xlabel('Pressure [MPa]')
plt.ylabel('Height z [m]')
plt.title('Pressure versus Height')
plt.savefig("PressureBWR.png", dpi=600)
plt.figure(6)
plt.plot(T_f_array, z_arrayplots)
plt.xlabel('Temperature [K]')
plt.ylabel('Height z [m]')
plt.title('Coolant Temperature vs Height')
plt.savefig("TempBulkBWR.png", dpi=600)
plt.figure(7)
plt.plot(T_F_Outer, z_arrayplots, label='Fuel Outer Surface Temp')
plt.plot(T_F_Center, z_arrayplots, label='Fuel Centerline Temp')
plt.legend(loc='upper left')
plt.xlabel("Temperature [K]")
plt.ylabel("Height z [m]")
plt.savefig("TempFuelBWR.png", dpi=600)
# density
plt.figure(8)
plt.plot(Density, z_arrayplots, label='Density')
plt.legend(loc='upper left')
plt.xlabel("Pressure [mPa]")
plt.ylabel("Height z [m]")
plt.savefig("Density", dpi=600)
# quality
plt.figure(9)
plt.plot(x, z_arrayplots, label='Quality')
plt.plot(xe, z_arrayplots, label='Quality')
plt.legend(loc='upper left')
plt.xlabel("Quality")
plt.ylabel("Height z [m]")
plt.savefig("Quality", dpi=600)
# void
plt.figure(10)
plt.plot(alpha, z_arrayplots, label='Void Fraction')
plt.legend(loc='upper left')
plt.xlabel("Void Fraction")
plt.ylabel("Height z [m]")
plt.savefig("Void Fraction", dpi=600)
tempdifference = T_C_Outer - T_f_array
print("Max clad vs bulk difference is " + str(np.amax(tempdifference)) + " C")
print("Max coolant temp is " + str(np.amax(T_f_array) - 273.15) + " C")
print("Max coolant temp is " + str(np.amax(T_f_array)) + " K")
print("Max clad temp is " + str(np.amax(T_C_Inner) - 273.15) + " C")
print("Max clad temp is " + str(np.amax(T_C_Inner)) + " K")
print("Max fuel temp is " + str(np.amax(T_F_Center) - 273.15) + " C")
print("Max fuel temp is " + str(np.amax(T_F_Center)) + " K")
print("Max fuel temp is " + str(np.amax(T_F_Outer) - 273.15) + " C")
print("Max fuel temp is " + str(np.amax(T_F_Outer)) + " K")
print("Max centerline temp occurs at z = " + str(z_CL_max) + "m")
MDNBR = np.amin(DNBR)
print("MDNBR is " + str(MDNBR))

Related

Where is my code hanging (in an infinite loop)?

I am new to Python and trying to get this script to run, but it seems to be hanging in an infinite loop. When I use ctrl+c to stop it, it is always on line 103.
vs = 20.05 * np.sqrt(Tb + Lb * (y - y0)) # m/s speed of sound as a function of temperature
I am used to MatLab (from school) and the editor it has. I ran into issues earlier with the encoding for this code. Any suggestions on a (free) editor? I am currently using JEdit and/or Notepad.
Here is the full script:
#!/usr/bin/env python
# -*- coding: ANSI -*-
import numpy as np
from math import *
from astropy.table import Table
import matplotlib.pyplot as plt
from hanging_threads import start_monitoring#test for code hanging
start_monitoring(seconds_frozen=10, test_interval=100)
"""Initial Conditions and Inputs"""
d = 154.71/1000 # diameter of bullet (in meters)
m = 46.7 # mass of bullet ( in kg)
K3 = 0.87*0.3735 # drag coefficient at supersonic speed
Cd1 = 0.87*0.108 #drag coefficient at subsonic speed
v0 = 802 # muzzle velocity in m/sec
dt = 0.01 # timestep in seconds
"""coriolis inputs"""
L = 90*np.pi/180 # radians - latitude of firing site
AZ = 90*np.pi/180 # radians - azimuth angle of fire measured clockwise from North
omega = 0.0000727 #rad/s rotation of the earth
"""wind inputs"""
wx = 0 # m/s
wz = 0 # m/s
"""initializing variables"""
vx = 0 #initial x velocity
vy = 0 #initial y velocity
vy0 = 0
y_max = 0 #apogee
v = 0
t = 0
x = 0
"""Variable Atmospheric Pressure"""
rho0 = 1.2041 # density of air at sea-level (kg/m^3)
T = 20 #temperature at sea level in celcius
Tb = T + 273.15 # temperature at sea level in Kelvin
Lb = -2/304.8 # temperature lapse rate in K/m (-2degrees/1000ft)- not valid above 36000ft
y = 0 # current altitude
y0 = 0 # initial altitude
g = 9.81 # acceleration due to gravity in m/s/s
M = 0.0289644 #kg/mol # molar mass of air
R = 8.3144598 # J/molK - universal gas constant
# air density as a function of altitude and temperature
rho = rho0 * ((Tb/(Tb+Lb*(y-y0)))**(1+(g*M/(R*Lb))))
"""Variable Speed of Sound"""
vs = 20.05*np.sqrt(Tb +Lb*(y-y0)) # m/s speed of sound as a function of temperature
Area = pi*(d/2)**2 # computing the reference area
phi_incr = 5 #phi0 increment (degrees)
N = 12 # length of table
"""Range table"""
dtype = [('phi0', 'f8'), ('phi_impact', 'f8'), ('x', 'f8'), ('z', 'f8'),('y', 'f8'), ('vx', 'f8'), ('vz', 'f8'), ('vy', 'f8'), ('v', 'f8'),('M', 'f8'), ('t', 'f8')]
table = Table(data=np.zeros(N, dtype=dtype))
"""Calculates entire trajectory for each specified angle"""
for i in range(N):
phi0 = (i + 1) * phi_incr
"""list of initial variables used in while loop"""
t = 0
y = 0
y_max = y
x = 0
z = 0
vx = v0*np.cos(radians(phi0))
vy = v0*np.sin(radians(phi0))
vx_w = 0
vz_w = 0
vz = 0
v = v0
ay = 0
ax = 0
wx = wx
wz = wz
rho = rho0 * ((Tb / (Tb + Lb * (y - y0))) ** (1 + (g * M / (R * Lb))))
vs = 20.05 * np.sqrt(Tb + Lb * (y - y0)) # m/s speed of sound as a function of temperature
ax_c = -2 * omega * ((vz * sin(L)) + vy * cos(L) * sin(AZ))
ay_c = 2 * omega * ((vz * cos(L) * cos(AZ)) + vx_w * cos(L) * sin(AZ))
az_c = -2 * omega * ((vy * cos(L) * cos(AZ)) - vx_w * sin(L))
Mach = v/vs
""" initializing variables for plots"""
t_list = [t]
x_list = [x]
y_list = [y]
vy_list = [vy]
v_list = [v]
phi0_list = [phi0]
Mach_list = [Mach]
while y >= 0:
phi0 = phi0
"""drag calculation with variable density, Temp and sound speed"""
rho = rho0 * ((Tb / (Tb + Lb * (y - y0))) ** (1 + (g * M / (R *Lb))))
vs = 20.05 * np.sqrt(Tb + Lb * (y - y0)) # m/s speed of sound as a function of temperature
Cd3 = K3 / sqrt(v / vs)
Mach = v/vs
"""Determining drag regime"""
if v > 1.2 * vs: #supersonic
Cd = Cd3
elif v < 0.8 * vs: #subsonic
Cd = Cd1
else: #transonic
Cd = ((Cd3 - Cd1)*(v/vs - 0.8)/(0.4)) + Cd1
"""Acceleration due to Coriolis"""
ax_c = -2*omega*((vz_w*sin(L))+ vy*cos(L)*sin(AZ))
ay_c = 2*omega*((vz_w*cos(L)*cos(AZ))+ vx_w*cos(L)*sin(AZ))
az_c = -2*omega*((vy*cos(L)*cos(AZ))- vx_w*sin(L))
"""Total acceleration calcs"""
if vx > 0:
ax = -0.5*rho*((vx-wx)**2)*Cd*Area/m + ax_c
else:
ax = 0
""" Vy before and after peak"""
if vy > 0:
ay = (-0.5 * rho * (vy ** 2) * Cd * Area / m) - g + ay_c
else:
ay = (0.5 * rho * (vy ** 2) * Cd * Area / m) - g + ay_c
az = az_c
vx = vx + ax*dt # vx without wind
# vx_w = vx with drag and no wind + wind
vx_w = vx + 2*wx*(1-(vx/v0*np.cos(radians(phi0))))
vy = vy + ay*dt
vz = vz + az*dt
vz_w = vz + wz*(1-(vx/v0*np.cos(radians(phi0))))
"""projectile velocity"""
v = sqrt(vx_w**2 + vy**2 + vz**2)
"""new x, y, z positions"""
x = x + vx_w*dt
y = y + vy*dt
z = z + vz_w*dt
if y_max <= y:
y_max = y
phi_impact = degrees(atan(vy/vx)) #impact angle in degrees
""" appends selected data for ability to plot"""
t_list.append(t)
x_list.append(x)
y_list.append(y)
vy_list.append(vy)
v_list.append(v)
phi0_list.append(phi0)
Mach_list.append(Mach)
if y < 0:
break
t += dt
"""Range table output"""
table[i] = ('%.f' % phi0, '%.3f' % phi_impact, '%.1f' % x,'%.2f' % z, '%.1f' % y_max, '%.1f' % vx_w,'%.1f' % vz,'%.1f' % vy,'%.1f' % v,'%.2f' %Mach, '%.1f' % t)
""" Plot"""
plt.plot(x_list, y_list, label='%d°' % phi0)#plt.plot(x_list, y_list, label='%d°' % phi0)
plt.title('Altitude versus Range')
plt.ylabel('Altitude (m)')
plt.xlabel('Range (m)')
plt.axis([0, 30000, 0, 15000])
plt.grid(True)
print(table)
legend = plt.legend(title="Firing Angle",loc=0, fontsize='small', fancybox=True)
plt.show()
Thank you in advance
Which Editor Should I Use?
Personally, I prefer VSCode, but Sublime is also pretty popular. If you really want to go barebones, try Vim. All three are completely free.
Code Errors
After scanning your code snippet, it appears that you are caught in an infinite loop, which you enter with the statement while y >= 0. The reason you always get line 103 when you hit Ctrl+C is likely because that takes the longest, making it more likely to land there at any given time.
Note that currently, you can only escape your while loop through this branch:
if y_max <= y:
y_max= y
phi_impact = degrees(atan(vy/vx)) #impact angle in degrees
""" appends selected data for ability to plot"""
t_list.append(t)
x_list.append(x)
y_list.append(y)
vy_list.append(vy)
v_list.append(v)
phi0_list.append(phi0)
Mach_list.append(Mach)
if y < 0:
break
t += dt
This means that if ymax never drops below y, or y never drops below zero, then you will infinitely loop. Granted, I haven't looked at your code in any great depth, but from the surface it appears that y_max is never decremented (meaning it will always be at least equal to y). Furthermore, y is only updated when you do y = y + vy*dt, which will only ever increase y if vy >= 0 (I assume dt is always positive).
Debugging
As #Giacomo Catenazzi suggested, try printing out y and y_max at the top of the while loop and see how they change as your code runs. I suspect they are not decrementing like you expected.

UDF value error for complex itterative function

I want to create an UDF for my excel worksheet. However when I select my input for my UDF I get a value error. Can someone help me?
Code and images below:
code:
Public Function pipediameter(Pth As Double) As Double
Dim D As Double
p = 150
Tv = 30
T = 55
k = 0.000045
vi = 4
a = (1.729 * (10 ^ (-6))) / ((1 + (T / 25)) ^ 1.165)
rho = 988
Cp = 4180
di = 1
i = 1
While i <= 10
v = 4 * Pth / (3.14 * di ^ 2 * Cp * rho * Tv)
Re = v * di / vi
B1 = (0.774 * Log(Re) - 1.41) / (1 + 1.32 * Sqr(k / di))
B2 = ((k * Re) / (3.7 * di)) + (2.51 * B1)
Y = (B1 - ((B1 + (2 * (Log(B2 / Re) / Log(10)))) / (1 + (2.18 / B2)))) ^ (-2)
D = (((8 * Y) / (p * rho)) * ((Pth) / (3.14 * Cp * Tv)) ^ 2) ^ 0.2
di = D
i = i + 1
Wend
pipediameter = D
End Function

How do I use multithreading on this function for a np.meshgrid of values?

The following code generates numpy 2D lists of r and E values for the specified intervals.
r = np.linspace(3, 14, 10)
E = np.linspace(0.05, 0.75, 10)
r, E = np.meshgrid(r, E)
I am then using the following nested loop to generate output from the function ionisationGamma for each r and E interval value.
for ridx in trange(len(r)):
z = []
for cidx in range(len(r[ridx])):
z.append(ionisationGamma(r[ridx][cidx], E[ridx][cidx]))
Z.append(z)
Z = np.array(Z)
This loop gives me a 2D numpy array Z, which is my output and I am using it for a 3D graph. The problem with it is: it is taking ~6 hours to generate the output for all these intervals as there are so many values due to np.meshgrid. I have just discovered multi-threading in Python and wanted to know how I can implement this by using it. Any help is appreciated.
See below code for ionisationGamma
def ionisationGamma(r, E):
I = complex(0.1, 1.0)
a_soft = 1.0
omega = 0.057
beta = 0.0
dt = 0.1
steps = 10000
Nintervals = 60
N = 3000
xmin = float(-300)
xmax = -xmin
x = [0.0]*N
dx = (xmax - xmin) / (N - 1)
L = dx * N
dk = 2 * M_PI / L
propagator = None
in_, out_, psi0 = None, None, None
in_ = [complex(0.,0.)] * N
psi0 = [complex(0.,0.)] * N
out_ = [[complex(0.,0.)]*N for i in range(steps+1)]
overlap = exp(-r) * (1 + r + (1 / 3) * pow(r, 2))
normC = 1 / (sqrt(2 * (1 + overlap)))
gammai = 0.5
qi = 0.0 + (r / 2)
pi = 0.0
gammai1 = 0.5
gammai2 = 0.5
qi1 = 0.0 - (r / 2)
qi2 = 0.0 + (r / 2)
pi1 = 0.0
pi2 = 0.0
# split initial wavepacket
for i in range(N):
x[i] = xmin + i * dx
out_[0][i] = (normC) * ((pow(gammai1 / M_PI, 1. / 4.) * exp(complex(-(gammai1 / 2.) * pow(x[i] - qi1, 2.), pi1 * (x[i] - qi1)))) + (pow(gammai2 / M_PI, 1. / 4.) * exp(complex(-(gammai2 / 2.) * pow(x[i] - qi2, 2.), pi2 * (x[i] - qi2)))))
in_[i] = (normC) * ((pow(gammai1 / M_PI, 1. / 4.) * exp(complex(-(gammai1 / 2.) * pow(x[i] - qi1, 2.), pi1 * (x[i] - qi1)))) + (pow(gammai2 / M_PI, 1. / 4.) * exp(complex(-(gammai2 / 2.) * pow(x[i] - qi2, 2.), pi2 * (x[i] - qi2)))))
psi0[i] = in_[i]
for l in range(1, steps+1):
for i in range(N):
propagator = exp(complex(0, -potential(x[i], omega, beta, a_soft, r, E, dt, l) * dt / 2.))
in_[i] = propagator * in_[i];
in_ = np.fft.fft(in_, N)
for i in range(N):
k = dk * float(i if i < N / 2 else i - N)
propagator = exp(complex(0, -dt * pow(k, 2) / (2.)))
in_[i] = propagator * in_[i]
in_ = np.fft.ifft(in_, N)
for i in range(N):
propagator = exp(complex(0, -potential(x[i], omega, beta, a_soft, r, E, dt, l) * dt / 2.))
in_[i] = propagator * in_[i]
out_[l][i] = in_[i]
initialGammaCentre = 0.0
finalGammaCentre = 0.0
for i in range(500, 2500 +1):
initialGammaCentre += pow(abs(out_[0][i]), 2) * dx
finalGammaCentre += pow(abs(out_[steps][i]), 2) * dx
ionisationGamma = finalGammaCentre / initialGammaCentre
return ionisationGamma
def potential(x, omega, beta, a_soft, r, E, dt, l):
V = (-1. / sqrt((x - (r / 2)) * (x - (r / 2)) + a_soft * a_soft)) + ((-1. / sqrt((x + (r / 2)) * (x + (r / 2)) + a_soft * a_soft))) + E * x
return V
Since the question is about how to use multiprocessing, the following code will work:
import multiprocessing as mp
if __name__ == '__main__':
with mp.Pool(processes=16) as pool:
Z = pool.starmap(ionisationGamma, arguments)
Z = np.array(Z)
Where the arguments are:
arguments = list()
for ridx in range(len(r)):
for cidx in range(len(r[ridx])):
arguments.append((r[ridx][cidx], E[ridx][cidx]))
I am using starmap instead of map, since you have multiple arguments that you want to unpack. This will divide the arguments iterable over multiple cores, using the ionisationGamma function and the final result will be ordered.
However, I do feel the need to say that the main solution is not really the multiprocessing but the original function code. In ionisationGamma you are using several times the slow python for loops. And it would benefit your code a lot if you could vectorize those operations.
A second observation is that you are using many of those loops separately and it would be nice if you could separate that one big function into multiple smaller functions. Then you can time every function individually and speed up those that are too slow.

Optimize 2D numpy array creation loop

I have the following code, which I'd like to optimize. Unfortunately, I can't find a way to gain speed or vectorize anything.
from scipy.sparse import diags
import numpy as np
def _compute_matrix_a(points, dw, dl, coefficient):
"""
"""
coefficient = coefficient.reshape(points, order='F')
extradl = coefficient[:,0] * 3
extradw = coefficient[0] * 3
#Build diagonals
diagonal_a = []
diagonal_b = []
diagonal_c = []
diagonal_d = []
diagonal_e = []
for idx, (k, i) in enumerate(product(range(points[1]), range(points[0]))):
if k == 0:
continue
if k <= 1:
pass
elif k < points[1] - 1:
a = 1 / (4 * dl**2) * (coefficient[i][k-1] - coefficient[i][k+1])\
+ coefficient[i][k] / dl**2
diagonal_a.append(a)
else:
a = coefficient[i][k-1] / (dl + extradl[i])**2\
+ coefficient[i][k] / (dl**2 / 2 + extradl[i]**2 / 2)
diagonal_a.append(a)
if k == 0 or (k == 1 and i == 0):
pass
elif i == 0:
b = 0
diagonal_b.append(b)
elif i < points[0] - 1:
b = 1 / (4 * dw**2) * (coefficient[i-1][k] - coefficient[i+1][k]) \
+ coefficient[i][k] * (1 / dw**2 - 1 / (2 * i * dw**2))
diagonal_b.append(b)
else:
b = coefficient[i-1][k] / (dw + extradw[k]) ** 2 \
+ coefficient[i][k] / (dw**2 / 2 + extradw[k]**2 / 2) \
- coefficient[i][k] / (i * dw * (dw + extradw[k]))
diagonal_b.append(b)
if k == 0:
pass
elif i == 0:
if k < points[1] - 1:
c = - 4 * coefficient[i][k] / dw**2\
- 2 * coefficient[i][k] / dl**2
else:
c = - 4 * coefficient[i][k] / dw**2\
- 2 * coefficient[i][k] / (dl**2 / 2 + extradl[i]**2 / 2)
diagonal_c.append(c)
elif i < points[0] - 1:
if k < points[1] - 1:
c = - 2 * coefficient[i][k] / dl**2 \
- 2 * coefficient[i][k] / dw**2
else:
c = - 2 * coefficient[i][k] / dw**2 \
- 2 * coefficient[i][k] / (dl**2 / 2 + extradl[i]**2 / 2)
diagonal_c.append(c)
else:
if k < points[1] - 1:
c = - 2 * coefficient[i][k] / (dw**2 / 2 + extradw[k]**2 / 2) \
- 2 * coefficient[i][k] / dl**2
else:
c = - 2 * coefficient[i][k] / (dw**2 / 2 + extradw[k]**2 / 2) \
- 2 * coefficient[i][k] / (dl**2 / 2 + extradl[i]**2 / 2)
diagonal_c.append(c)
if k == 0 or (k == points[1] - 1 and i == points[0] - 1):
pass
elif i == 0:
d = 4 * coefficient[i][k] / dw**2
diagonal_d.append(d)
elif i == points[0] - 1:
d = 0
diagonal_d.append(d)
else:
d = 1 / (4 * dw ** 2) * (coefficient[i+1][k] - coefficient[i-1][k]) \
+ coefficient[i][k] * (1 / dw**2 + 1 / (2 * i * dw**2))
diagonal_d.append(d)
if k == 0 or k == points[1] - 1:
pass
else:
e = 1 / (4 * dl**2) * (coefficient[i][k+1] - coefficient[i][k-1])\
+ coefficient[i][k] / dl**2
diagonal_e.append(e)
diagonals = [diagonal_a, diagonal_b, diagonal_c, diagonal_d, diagonal_e]
mat_a = diags(diagonals, [-points[0], -1, 0, 1, points[0]]).toarray()
return mat_a
mesh_points = (20, 50)
coefficients = np.random.rand(mesh_points[0], mesh_points[1])
dwidth = 100.
dlength = 100.
mymatrix = _compute_matrix_a(mesh_points, dwidth, dlength, coefficients)
I can't seem to find a way around my two loops (itertool product) to create the matrix.
I tried using np.roll:
# This gets the k-1
coefficients_km1 = np.roll(coefficients, 1, axis=0)
# This gets the i-1
coefficients_im1 = np.roll(coefficients, 1, axis=1)
# This gets the k+1
coefficients_kp1 = np.roll(coefficients, -1, axis=0)
# This gets the i+1
coefficients_ip1 = np.roll(coefficients, -1, axis=1)
Unfortunately, I couldn't convert the idea fully and got stuck in creating the array.
I'm open to any suggestion to optimize this function.

Surface Area of a Spheroid in Python

I'm trying to write a function that calculates the surface area of a prolate or oblate spheroid. Here's a link to where I got the formulas (http://en.wikipedia.org/wiki/Prolate_spheroid & http://en.wikipedia.org/wiki/Oblate_spheroid). I think I've written them wrong, but here is my code so far;
from math import pi, sqrt, asin, degrees, atanh
def checkio(height, width):
height = float(height)
width = float(width)
my_list = []
if height == width:
r = 0.5 * width
surface_area = 4 * pi * r**2
surface_area = round(surface_area, 2)
my_list.append(surface_area)
elif height > width: #If spheroid is prolate
a = 0.5 * width
b = 0.5 * height
e2 = 1 - a**2 / b**2
e = sqrt(e2)
surface_area = 2 * pi * a**2 * (1 + b / (a * e) * asin(e)))
surface_area = round(surface_area, 2)
my_list.append(surface_area)
elif height < width: #If spheroid is oblate
a = 0.5 * width
b = 0.5 * height
e2 = 1 - b**2 / a**2
e = sqrt(e2)
surface_area = 2 * pi * a**2 * (1 + (1 - e2) / e * atanh(e))
surface_area = round(surface_area, 2)
my_list.append(surface_area)
return my_list

Resources