# Version 1.1 released by Yi-Chuan Lu on February 23, 2023. # Release 1.1 accommodates old Python 2 installations that # interpret some constants as integers instead of reals. # Version 1.0 released by Yi-Chuan Lu on May 18, 2022. # # When using this code, please cite: # # @article{20heatindex, # Title = {Extending the Heat Index}, # Author = {Yi-Chuan Lu and David M. Romps}, # Journal = {Journal of Applied Meteorology and Climatology}, # Year = {2022}, # Volume = {61}, # Number = {10}, # Pages = {1367--1383}, # Year = {2022}, # } # # This headindex function returns the Heat Index in Kelvin. The inputs are: # - T, the temperature in Kelvin # - RH, the relative humidity, which is a value from 0 to 1 # - show_info is an optional logical flag. If true, the function returns the physiological state. import math # Thermodynamic parameters Ttrip = 273.16 # K ptrip = 611.65 # Pa E0v = 2.3740e6 # J/kg E0s = 0.3337e6 # J/kg rgasa = 287.04 # J/kg/K rgasv = 461. # J/kg/K cva = 719. # J/kg/K cvv = 1418. # J/kg/K cvl = 4119. # J/kg/K cvs = 1861. # J/kg/K cpa = cva + rgasa cpv = cvv + rgasv # The saturation vapor pressure def pvstar(T): if T == 0.0: return 0.0 elif T phi_salt * pvstar(Ts)): # region V Ts = solve( lambda Ts : (Ts-Ta)/Ra_un(Ts,Ta) + (phi_salt*pvstar(Ts)-Pa)/Za_un -(Q-Qv(Ta,Pa)), 0.,Tc,tol,maxIter) Rs = (Tc-Ts)/(Q-Qv(Ta,Pa)) eqvar_name = "Rs*" else: # region VI Rs = 0. eqvar_name = "dTcdt" dTcdt = (1./C)* flux3 return [eqvar_name,phi,Rf,Rs,dTcdt] # given the equivalent variable, find the Heat Index def find_T(eqvar_name,eqvar): if (eqvar_name == "phi"): T = solve(lambda T: find_eqvar(T,1.)[1]-eqvar,0.,240.,tolT,maxIter) region = 'I' elif (eqvar_name == "Rf"): T = solve(lambda T: find_eqvar(T,min(1.,Pa0/pvstar(T)))[2]-eqvar,230.,300.,tolT,maxIter) region = ('II' if Pa0>pvstar(T) else 'III') elif (eqvar_name == "Rs" or eqvar_name == "Rs*"): T = solve(lambda T: find_eqvar(T,Pa0/pvstar(T))[3]-eqvar,295.,350.,tolT,maxIter) region = ('IV' if eqvar_name == "Rs" else 'V') else: T = solve(lambda T: find_eqvar(T,Pa0/pvstar(T))[4]-eqvar,340.,1000.,tolT,maxIter) region = 'VI' return T, region # combining the two functions find_eqvar and find_T def heatindex(Ta,RH,show_info=False): dic = {"phi":1,"Rf":2,"Rs":3,"Rs*":3,"dTcdt":4} eqvars = find_eqvar(Ta,RH) T, region = find_T(eqvars[0],eqvars[dic[eqvars[0]]]) if (Ta == 0.): T = 0. if (show_info==True): if region=='I': print("Region I, covering (variable phi)") print("Clothing fraction is "+ str(round(eqvars[1],3))) elif region=='II': print("Region II, clothed (variable Rf, pa = pvstar)") print("Clothing thickness is "+ str(round((eqvars[2]/16.7)*100.,3))+" cm") elif region=='III': print("Region III, clothed (variable Rf, pa = pref)") print("Clothing thickness is "+ str(round((eqvars[2]/16.7)*100.,3))+" cm") elif region=='IV': kmin = 5.28 # W/K/m^2 , conductance of tissue rho = 1.0e3 # kg/m^3 , density of blood c = 4184. # J/kg/K , specific heat of blood print("Region IV, naked (variable Rs, ps < phisalt*pvstar)") print("Blood flow is " + str(round(( (1./eqvars[3] - kmin)*A/(rho*c) ) *1000.*60.,3))+" l/min") elif region=='V': kmin = 5.28 # W/K/m^2 , conductance of tissue rho = 1.0e3 # kg/m^3 , density of blood c = 4184. # J/kg/K , specific heat of blood print("Region V, naked dripping sweat (variable Rs, ps = phisalt*pvstar)") print("Blood flow is " + str(round(( (1./eqvars[3] - kmin)*A/(rho*c) ) *1000.*60.,3))+" l/min") else: print("Region VI, warming up (dTc/dt > 0)") print("dTc/dt = "+ str(round(eqvars[4]*3600.,6))+ " K/hour") return T def solve(f,x1,x2,tol,maxIter): a = x1 b = x2 fa = f(a) fb = f(b) if fa*fb>0.: raise SystemExit('wrong initial interval in the root solver') return None else: for i in range(maxIter): c = (a+b)/2. fc = f(c) if fb*fc > 0. : b = c fb = fc else: a = c fa = fc if abs(a-b) < tol: return c if i == maxIter-1: raise SystemExit('reaching maximum iteration in the root solver') return None