def stpv_pv_filter_fom(trans, ref, lam): ### set lambda_bg to 750 nm lbg = 750e-9 ### get AM1.5 spectrum AM = datalib.AM(lam) ### get BB spectrum at 440 K BBs = datalib.BB(lam, 440) ### There are three different integrands for numerator num_integrand_1 = np.copy(AM * trans * lam / lbg) num_integrand_2 = np.copy(AM * trans) num_integrand_3 = np.copy(BBs * ref) num1 = numlib.Integrate(num_integrand_1, lam, 300e-9, lbg) num2 = numlib.Integrate(num_integrand_2, lam, lbg, 3200e-9) num3 = numlib.Integrate(num_integrand_3, lam, 3200e-9, 3700e-9) ### denominator 1 comes from lam/lbg * AM1.5 den_integrand_1 = np.copy(AM * lam / lbg) den1 = numlib.Integrate(den_integrand_1, lam, 300e-9, lbg) ### denominator 2 comes from AM1.5 den2 = numlib.Integrate(AM, lam, lbg, 3200e-9) ### denominator 3 comes from BB spectrum return 0.5 * num1 / den1 + 0.5 * num2 / den2 + 2 * num2 / den2
def SpectralEfficiency_grad(dim, lam, lbg, emissivity, emissivity_prime, BBs): ### ininitalize gradient vector grad = np.zeros(dim) TE = emissivity * BBs ynum = TE * lam / lbg upper = np.amax(lam) ### normal numerator (rho) rho = numlib.Integrate(ynum, lam, 1e-9, lbg) ### normal denomenator (P) P = numlib.Integrate(TE, lam, 1e-9, upper) ### loop over degrees of freedom and get gradient elements for i in range(0, dim): ### derivative of thermal emission wrt layer thickness, also integrand for P_prime TE_prime = BBs * emissivity_prime[i, :] ### integrand for rho_prime num_prime = TE_prime * lam / lbg ### rho_prime rho_prime = numlib.Integrate(num_prime, lam, 1e-9, lbg) ### P_prime P_prime = numlib.Integrate(TE_prime, lam, 1e-9, upper) ### compute gradient element grad[i] = (rho_prime * P - P_prime * rho) / (P**2) ### return gradient return grad
def SpectralEfficiency(TE, lam, lbg): ynum = TE * lam / lbg upper = np.amax(lam) num = numlib.Integrate(ynum, lam, 1e-9, lbg) den = numlib.Integrate(TE, lam, 1e-9, upper) SE = num / den return SE
def Abs_eff(lam, EM, solarconc, T): AM = datalib.AM(lam) upper = np.amax(lam) BBs = datalib.BB(lam, T) TE = BBs * EM alpha = solarconc * (numlib.Integrate(AM * EM, lam, 100e-9, upper)) beta = np.pi * numlib.Integrate(TE, lam, 100e-9, upper) return (alpha - beta) / (alpha)
def normalized_power(lam, TE, BB): upper = np.amax(lam) ph = datalib.PhLum(lam) num = ph * TE den = ph * BB numerator = numlib.Integrate(num, lam, 0, upper) denominator = numlib.Integrate(den, lam, 0, upper) return numerator / denominator
def Lum_efficiency(lam, TE): upper = np.amax(lam) ph = datalib.PhLum(lam) num = ph * TE numerator = numlib.Integrate(num, lam, 0, upper) den = TE denominator = numlib.Integrate(den, lam, 0, upper) return (numerator / denominator)
def Jagg_enhancement(emissivity, lam): upper = np.amax(lam) jg = datalib.JAgg_Abs(lam) num = jg * emissivity numerator = numlib.Integrate(num, lam, 0, upper) den = jg * jg denominator = numlib.Integrate(den, lam, 0, upper) return (numerator / denominator)
def lum_efficiency_filter(lam, BBs, emissivity, transmissivity): upper = np.amax(lam) ph = datalib.PhLum(lam) ### total observed thermal emission is BB spectrum * emissivity of emitter * transmissivity of filter TE = BBs * emissivity * transmissivity num = ph * TE numerator = numlib.Integrate(num, lam, 0, upper) denominator = numlib.Integrate(TE, lam, 0, upper) return (numerator / denominator)
def Lum_efficiency_prime(lam, TE, TE_prime): upper = np.amax(lam) ph = datalib.PhLum(lam) num = ph * TE num_prime = ph * TE_prime numerator = numlib.Integrate(num, lam, 0, upper) numerator_prime = numlib.Integrate(num_prime, lam, 0, upper) denominator = numlib.Integrate(TE, lam, 0, upper) denominator_prime = numlib.Integrate(TE_prime, lam, 0, upper) return (denominator * numerator_prime - numerator * denominator_prime) / (denominator**2)
def Jagg_enhancement_prime(dim, lam, emissivity, emissivity_prime): grad = np.zeros(dim) upper = np.amax(lam) #upper = np.amax(lam) ### we want the absorption spectrum of the lone J-Agg layer, not just the refractive index jg = datalib.JAgg_Abs(lam) denominator = jg * jg ### denominator intergral only needs to be computed once den = numlib.Integrate(denominator, lam, 0, upper) for i in range(0, dim): numerator = emissivity_prime[i, :] * jg num_prime = numlib.Integrate(numerator, lam, 0, upper) grad[i] = num_prime / den return grad
def multi_spectral_efficiency(lam, light, lbg1, lbg2): ### upper-bound of light-source upper = np.amax(lam) ### integrand for PV 1 num_integrand_1 = light * lam / lbg1 ### integrand for PV 2 num_integrand_2 = light * lam / lbg2 ### numerator 1 numerator_1 = numlib.Integrate(num_integrand_1, lam, 1e-9, lbg1) ### numerator 2 numerator_2 = numlib.Integrate(num_integrand_2, lam, lbg1, lbg2) ### denominator denominator = numlib.Integrate(light, lam, 1e-9, upper) return numerator_1, numerator_2, denominator
def ambient_jsc(eps, lam, lbg): ### get upper bound of integral upper = np.amax(lam) ### get AM1.5 spectrum AM = datalib.AM(lam) ### get spectral response function (currently only Si supported for ### traditional PV... more to come soon) SR = datalib.SR_Si(lam) ### jsc integrand integrand = AM * SR * eps ### integrate it! jsc = numlib.Integrate(integrand, lam, 1e-9, upper) return jsc
def lum_efficiency_prime(dim, lam, emissivity, emissivity_prime, BBs): ### allocate gradient vector grad = np.zeros(dim) ### get data that will not change for each element of the gradient first! upper = np.amax(lam) ph = datalib.PhLum(lam) TE = emissivity * BBs TE_prime = np.zeros(len(lam)) num = ph * TE numerator = numlib.Integrate(num, lam, 0, upper) denominator = numlib.Integrate(TE, lam, 0, upper) ### now loop through elements of gradient_list and fill in elements of grad for i in range(0, dim): TE_prime = BBs * emissivity_prime[i, :] num_prime = ph * TE_prime numerator_prime = numlib.Integrate(num_prime, lam, 0, upper) denominator_prime = numlib.Integrate(TE_prime, lam, 0, upper) grad[i] = (denominator * numerator_prime - numerator * denominator_prime) / (denominator**2) return grad
def jsc_multi(lam, TE, eps_pv1, eps_pv2, T_pv1): upper = np.amax(lam) ### get the spectral response of Silicon and store it to an array called sr1 sr1 = datalib.SR_Si(lam) ### get the spectral response of GaSb and store it to an array called sr1 sr2 = datalib.SR_GaSb(lam) ### create integrand for jsc1 int_1 = sr1 * eps_pv1 * TE ### create integrand for jsc2 int_2 = sr2 * eps_pv2 * TE * T_pv1 ### integrate the integrands! jsc1 = numlib.Integrate(int_1, lam, 1e-9, upper) jsc2 = numlib.Integrate(int_2, lam, 1e-9, upper) plt.plot(lam, int_1, 'red', label='Integrand 1') plt.plot(lam, int_2, 'blue', label='Integrand 2') plt.legend() plt.show() return jsc1, jsc2
def JSC(TE, lam, PV): ### hard-coding view factor for now! F = 0.84 ### get spectral response function for appropriate PV material if (PV == 'InGaAsSb'): SR = datalib.SR_InGaAsSb(lam) elif (PV == 'GaSb'): SR = datalib.SR_GaSb(lam) else: SR = datalib.SR_InGaAsSb(lam) ### get upper limit of lambda array... will integrate over entire ### range, in principle spectral response function will vanish at the ### appropriate boundaries of lambda upper = np.amax(lam) integrand = TE * SR * F * np.pi jshc = numlib.Integrate(integrand, lam, 1e-9, upper) return jshc
def ambient_jsc_grad(dim, eps_prime, lam, lbg): ### allocate grad! grad = np.zeros(dim) ### get upper bound of integral upper = np.amax(lam) ### get the AM1.5 spectrum AM = datalib.AM(lam) ### get the spectral response of Si SR = datalib.SR_Si(lam) ### Loop over the layers in gradient_list... compute jsc_prime for each one and store in grad! for i in range(0, dim): integrand = AM * SR * eps_prime[i, :] jsc_prime = numlib.Integrate(integrand, lam, 1e-9, upper) #print(" just computed Jsc' ... is is ",jsc_prime) grad[i] = jsc_prime return grad
def stpv_pv_filter_grad(dim, trans_prime, ref_prime, lam): lbg = 750e-9 grad = np.zeros(dim) AM = datalib.AM(lam) BBs = datalib.BB(lam, 440) den_integrand_1 = np.copy(AM * lam / lbg) den1 = numlib.Integrate(den_integrand_1, lam, 300e-9, lbg) den2 = numlib.Integrate(AM, lam, lbg, 3200e-9) den3 = numlib.Integrate(BBs, lam, 3200e-9, 3700e-9) for i in range(0, dim): integrand_1 = np.copy(trans_prime[i, :] * AM * lam / lbg) integrand_2 = np.copy(trans_prime[i, :] * AM) integrand_3 = np.copy(ref_prime[i, :] * BBs) num_prime_1 = numlib.Integrate(integrand_1, lam, 300e-9, lbg) num_prime_2 = numlib.Integrate(integrand_2, lam, lbg, 3200e-9) num_prime_3 = numlib.Integrate(integrand_3, lam, 3200e-9, 3700e-9) grad[ i] = 0.5 * num_prime_1 / den1 + 0.5 * num_prime_2 / den2 + 2 * num_prime_3 / den3 return grad
def FalseColor_FromSpec(TE, lam): ### get color response functions #cie = datalib.CIE((lam+1500e-9)*400e-9/2400e-9) SR = datalib.SR_InGaAsSb(lam) #plt.plot(1e9*lam, cie['xbar'], 'red', 1e9*lam, cie['ybar'], 'green', 1e9*lam, cie['zbar'], 'blue') #plt.show() ### This will be the shifted color cone response model for InGaAsSb ### get X from TE spectrum #X = numlib.Integrate(TE*SR*cie['xbar'], lam, 100e-9, 4000e-9) ### get Y from TE spectrum #Y = numlib.Integrate(TE*SR*cie['ybar'], lam, 100e-9, 4000e-9) ### get Z from TE spectrum #Z = numlib.Integrate(TE*SR*cie['zbar'], lam, 100e-9, 4000e-9) ### this will be the step-function model for the response of ### InGaAsSb PV cell ### get X from TE spectrum only - red is a penalty coming from sub-bg emission X = numlib.Integrate(TE, lam, 2250e-9, 10000e-9) ### get Y from TE spectrum weighted by SR function... green is good! Y = numlib.Integrate(TE * SR, lam, 1900e-9, 2250e-9) ### get Z from TE spectrum weighted by SR function... blue is less good! Z = numlib.Integrate(TE * SR, lam, 400e-9, 1900e-9) ### get total magnitude tot = X + Y + Z ### get normalized values x = X / tot y = Y / tot z = Z / tot ## should also be equal to z = 1 - x - y ### array of xr, xg, xb, xw, ..., zr, zg, zb, zw ### use hdtv standard xrgbw = [0.670, 0.210, 0.150, 0.3127] yrgbw = [0.330, 0.710, 0.060, 0.3291] zrgbw = [] for i in range(0, len(xrgbw)): zrgbw.append(1. - xrgbw[i] - yrgbw[i]) #print("zrgbw is ",zrgbw) ## rx = yg*zb - yb*zg rx = yrgbw[1] * zrgbw[2] - yrgbw[2] * zrgbw[1] ## ry = xb*zg - xg*zb ry = xrgbw[2] * zrgbw[1] - xrgbw[1] * zrgbw[2] ## rz = (xg * yb) - (xb * yg) rz = xrgbw[1] * yrgbw[2] - xrgbw[2] * yrgbw[1] ## gx = (yb * zr) - (yr * zb) gx = yrgbw[2] * zrgbw[0] - yrgbw[0] * zrgbw[2] ## gy = (xr * zb) - (xb * zr) gy = xrgbw[0] * zrgbw[2] - xrgbw[2] * zrgbw[0] ## gz = (xb * yr) - (xr * yb) gz = xrgbw[2] * yrgbw[0] - xrgbw[0] * yrgbw[2] ## bx = (yr * zg) - (yg * zr) bx = yrgbw[0] * zrgbw[1] - yrgbw[1] * zrgbw[0] ## by = (xg * zr) - (xr * zg) by = xrgbw[1] * zrgbw[0] - xrgbw[0] * zrgbw[1] ## bz = (xr * yg) - (xg * yr) bz = xrgbw[0] * yrgbw[1] - xrgbw[1] * yrgbw[0] ## rw = ((rx * xw) + (ry * yw) + (rz * zw)) / yw; rw = (rx * xrgbw[3] + ry * yrgbw[3] + rz * zrgbw[3]) / yrgbw[3] ## gw = ((gx * xw) + (gy * yw) + (gz * zw)) / yw; gw = (gx * xrgbw[3] + gy * yrgbw[3] + gz * zrgbw[3]) / yrgbw[3] ## bw = ((bx * xw) + (by * yw) + (bz * zw)) / yw; bw = (bx * xrgbw[3] + by * yrgbw[3] + bz * zrgbw[3]) / yrgbw[3] ## /* xyz -> rgb matrix, correctly scaled to white. */ rx = rx / rw ry = ry / rw rz = rz / rw gx = gx / gw gy = gy / gw gz = gz / gw bx = bx / bw by = by / bw bz = bz / bw ## /* rgb of the desired point */ r = (rx * x) + (ry * y) + (rz * z) g = (gx * x) + (gy * y) + (gz * z) b = (bx * x) + (by * y) + (bz * z) rgblist = [] rgblist.append(r) rgblist.append(g) rgblist.append(b) # are there negative values? w = np.amin(rgblist) if w < 0: rgblist[0] = rgblist[0] - w rgblist[1] = rgblist[1] - w rgblist[2] = rgblist[2] - w # scale things so that max has value of 1 mag = np.amax(rgblist) rgblist[0] = rgblist[0] / mag rgblist[1] = rgblist[1] / mag rgblist[2] = rgblist[2] / mag #rgb = {'r': rgblist[0]/mag, 'g': rgblist[1]/mag, 'b': rgblist[2]/mag } return rgblist
def jagg_sd(self): self.jagg_sd_val = numlib.Integrate( self.emissivity_array, self.lambda_array, 500e-9, 700e-9) / 200e-9 return 1
def Pwr_den(TE, lam, lbg): PDA = (lam / lbg) * TE PD = numlib.Integrate(PDA, lam, 1e-9, lbg) return PD * np.pi
def RGB_FromSpec(TE, lam): ### get color response functions cie = datalib.CIE(lam) ### get X from TE spectrum X = numlib.Integrate(TE * cie['xbar'], lam, 380e-9, 780e-9) ### get Y from TE spectrum Y = numlib.Integrate(TE * cie['ybar'], lam, 380e-9, 780e-9) ### get Z from TE spectrum Z = numlib.Integrate(TE * cie['zbar'], lam, 380e-9, 780e-9) ### get total magnitude tot = X + Y + Z ### get normalized values x = X / tot y = Y / tot z = Z / tot ## should also be equal to z = 1 - x - y ### array of xr, xg, xb, xw, ..., zr, zg, zb, zw ### use hdtv standard xrgbw = [0.670, 0.210, 0.150, 0.3127] yrgbw = [0.330, 0.710, 0.060, 0.3291] zrgbw = [] for i in range(0, len(xrgbw)): zrgbw.append(1. - xrgbw[i] - yrgbw[i]) #print("zrgbw is ",zrgbw) ## rx = yg*zb - yb*zg rx = yrgbw[1] * zrgbw[2] - yrgbw[2] * zrgbw[1] ## ry = xb*zg - xg*zb ry = xrgbw[2] * zrgbw[1] - xrgbw[1] * zrgbw[2] ## rz = (xg * yb) - (xb * yg) rz = xrgbw[1] * yrgbw[2] - xrgbw[2] * yrgbw[1] ## gx = (yb * zr) - (yr * zb) gx = yrgbw[2] * zrgbw[0] - yrgbw[0] * zrgbw[2] ## gy = (xr * zb) - (xb * zr) gy = xrgbw[0] * zrgbw[2] - xrgbw[2] * zrgbw[0] ## gz = (xb * yr) - (xr * yb) gz = xrgbw[2] * yrgbw[0] - xrgbw[0] * yrgbw[2] ## bx = (yr * zg) - (yg * zr) bx = yrgbw[0] * zrgbw[1] - yrgbw[1] * zrgbw[0] ## by = (xg * zr) - (xr * zg) by = xrgbw[1] * zrgbw[0] - xrgbw[0] * zrgbw[1] ## bz = (xr * yg) - (xg * yr) bz = xrgbw[0] * yrgbw[1] - xrgbw[1] * yrgbw[0] ## rw = ((rx * xw) + (ry * yw) + (rz * zw)) / yw; rw = (rx * xrgbw[3] + ry * yrgbw[3] + rz * zrgbw[3]) / yrgbw[3] ## gw = ((gx * xw) + (gy * yw) + (gz * zw)) / yw; gw = (gx * xrgbw[3] + gy * yrgbw[3] + gz * zrgbw[3]) / yrgbw[3] ## bw = ((bx * xw) + (by * yw) + (bz * zw)) / yw; bw = (bx * xrgbw[3] + by * yrgbw[3] + bz * zrgbw[3]) / yrgbw[3] ## /* xyz -> rgb matrix, correctly scaled to white. */ rx = rx / rw ry = ry / rw rz = rz / rw gx = gx / gw gy = gy / gw gz = gz / gw bx = bx / bw by = by / bw bz = bz / bw ## /* rgb of the desired point */ r = (rx * x) + (ry * y) + (rz * z) g = (gx * x) + (gy * y) + (gz * z) b = (bx * x) + (by * y) + (bz * z) rgblist = [] rgblist.append(r) rgblist.append(g) rgblist.append(b) # are there negative values? w = np.amin(rgblist) if w < 0: rgblist[0] = rgblist[0] - w rgblist[1] = rgblist[1] - w rgblist[2] = rgblist[2] - w # scale things so that max has value of 1 mag = np.amax(rgblist) rgblist[0] = rgblist[0] / mag rgblist[1] = rgblist[1] / mag rgblist[2] = rgblist[2] / mag #rgb = {'r': rgblist[0]/mag, 'g': rgblist[1]/mag, 'b': rgblist[2]/mag } return rgblist
def p_in(TE, lam): integrand = TE * np.pi upper = np.amax(lam) p = numlib.Integrate(integrand, lam, 1e-9, upper) return p
def integrated_solar_power(lam): AM = datalib.AM(lam) upper = np.amax(lam) p_in = numlib.Integrate(AM, lam, 1e-9, upper) return p_in