def get_severe(self): ''' Function to calculate special severe weather indices. Requires calling get_parcels() and get_kinematics(). Returns nothing, but sets the following variables: self.stp_fixed - fixed layer significant tornado parameter self.stp_cin - effective layer significant tornado parameter self.right_scp - right moving supercell composite parameter self.left_scp - left moving supercell composite parameter Parameters ---------- None Returns ------- None ''' wspd = utils.mag(self.sfc_6km_shear[0], self.sfc_6km_shear[1]) self.stp_fixed = params.stp_fixed(self.sfcpcl.bplus, self.sfcpcl.lclhght, self.srh1km[0], utils.KTS2MS(wspd)) if self.etop is np.ma.masked or self.ebottom is np.ma.masked: self.right_scp = 0.0; self.left_scp = 0.0 self.stp_cin = 0.0 else: self.right_scp = params.scp( self.mupcl.bplus, self.right_esrh[0], utils.KTS2MS(self.ebwspd)) self.left_scp = params.scp( self.mupcl.bplus, self.left_esrh[0], utils.KTS2MS(self.ebwspd)) self.stp_cin = params.stp_cin(self.mlpcl.bplus, self.right_esrh[0], utils.KTS2MS(self.ebwspd), self.mlpcl.lclhght, self.mlpcl.bminus)
def helicity(prof, lower, upper, stu=0, stv=0, dp=-1, exact=True): ''' Calculates the relative helicity (m2/s2) of a layer from lower to upper. If storm-motion vector is supplied, storm-relative helicity, both positve and negative, is returned. Parameters ---------- prof : profile object Profile Object lower : number Bottom level of layer (m, AGL) upper : number Top level of layer (m, AGL) stu : number (optional; default = 0) U-component of storm-motion stv : number (optional; default = 0) V-component of storm-motion dp : negative integer (optional; default -1) The pressure increment for the interpolated sounding exact : bool (optional; default = True) Switch to choose between using the exact data (slower) or using interpolated sounding at 'dp' pressure levels (faster) Returns ------- phel+nhel : number Combined Helicity (m2/s2) phel : number Positive Helicity (m2/s2) nhel : number Negative Helicity (m2/s2) ''' if lower != upper: lower = interp.to_msl(prof, lower) upper = interp.to_msl(prof, upper) plower = interp.pres(prof, lower) pupper = interp.pres(prof, upper) if exact: ind1 = np.where(plower >= prof.pres)[0].min() ind2 = np.where(pupper <= prof.pres)[0].max() u1, v1 = interp.components(prof, plower) u2, v2 = interp.components(prof, pupper) u = np.concatenate([[u1], prof.u[ind1:ind2 + 1].compressed(), [u2]]) v = np.concatenate([[v1], prof.v[ind1:ind2 + 1].compressed(), [v2]]) else: ps = np.arange(plower, pupper + dp, dp) u, v = interp.components(prof, ps) sru = utils.KTS2MS(u - stu) srv = utils.KTS2MS(v - stv) layers = (sru[1:] * srv[:-1]) - (sru[:-1] * srv[1:]) phel = layers[layers > 0].sum() nhel = layers[layers < 0].sum() else: phel = nhel = 0 return phel + nhel, phel, nhel
def get_sars(self): ''' Function to get the SARS analogues from the hail and supercell databases. Requires calling get_kinematics() and get_parcels() first. Also calculates the significant hail parameter. Function returns nothing, but sets the following variables: self.matches - the matches from SARS HAIL self.ship - significant hail parameter self.supercell_matches - the matches from SARS SUPERCELL Parameters ---------- None Returns ------- None ''' sfc_6km_shear = utils.KTS2MS( utils.mag(self.sfc_6km_shear[0], self.sfc_6km_shear[1])) sfc_3km_shear = utils.KTS2MS( utils.mag(self.sfc_3km_shear[0], self.sfc_3km_shear[1])) sfc_9km_shear = utils.KTS2MS( utils.mag(self.sfc_9km_shear[0], self.sfc_9km_shear[1])) h500t = interp.temp(self, 500.) lapse_rate = params.lapse_rate(self, 700., 500., pres=True) srh3km = self.srh3km[0] srh1km = self.srh1km[0] mucape = self.mupcl.bplus mlcape = self.mlpcl.bplus mllcl = self.mlpcl.lclhght mumr = thermo.mixratio(self.mupcl.pres, self.mupcl.dwpc) self.ship = params.ship(self) ## Cambios para el hemisferio sur JP JP if self.latitude < 0: srh1km = -srh1km srh3km = -srh3km self.hail_database = 'sars_hail.txt' self.supercell_database = 'sars_supercell.txt' try: self.matches = hail(self.hail_database, mumr, mucape, h500t, lapse_rate, sfc_6km_shear, sfc_9km_shear, sfc_3km_shear, srh3km) except: self.matches = ([], [], 0, 0, 0) try: self.supercell_matches = supercell(self.supercell_database, mlcape, mllcl, h500t, lapse_rate, utils.MS2KTS(sfc_6km_shear), srh1km, utils.MS2KTS(sfc_3km_shear), utils.MS2KTS(sfc_9km_shear), srh3km) except Exception as e: self.supercell_matches = ([], [], 0, 0, 0)
def norm_wind_shear(prof, pbot=850, ptop=250): ''' Calculates the bulk shear between the wind at (pbot) and (ptop), normalized by dividing by the thickness of the layer. Parameters ---------- prof: profile object Profile object pbot : number (optional; default 850 hPa) Pressure of the bottom level (hPa) ptop : number (optional; default 250 hPa) Pressure of the top level (hPa) Returns ------- nws : number Normalized wind shear (Thousandths of units per second) ''' shr = utils.KTS2MS(utils.mag(*wind_shear(prof, pbot=pbot, ptop=ptop))) hbot = interp.hght(prof, pbot) htop = interp.hght(prof, ptop) thickness = htop - hbot nws = shr / thickness return nws
def norm_total_shear(prof, pbot=850, ptop=250, dp=-1, exact=True): ''' Calculates the total shear (also known as the hodograph length) between the wind at (pbot) and (ptop), normalized by dividing by the thickness of the layer. Parameters ---------- prof: profile object Profile object pbot : number (optional; default 850 hPa) Pressure of the bottom level (hPa) ptop : number (optional; default 250 hPa) Pressure of the top level (hPa) dp : negative integer (optional; default -1) The pressure increment for the interpolated sounding exact : bool (optional; default = True) Switch to choose between using the exact data (slower) or using interpolated sounding at 'dp' pressure levels (faster) Returns ------- norm_tot_pos_shr : number Normalized total positive shear norm_tot_neg_shr : number Normalized total negative shear norm_tot_net_shr : number Normalized total net shear (subtracting negative shear from positive shear) norm_tot_abs_shr : number Normalized total absolute shear (adding positive and negative shear together) ''' shr = utils.KTS2MS(np.asarray(total_shear(prof, pbot=pbot, ptop=ptop, dp=dp, exact=exact))) hbot = interp.hght(prof, pbot) htop = interp.hght(prof, ptop) thickness = htop - hbot norm_tot_pos_shr, norm_tot_neg_shr, norm_tot_net_shr, norm_tot_abs_shr = shr / thickness return norm_tot_pos_shr, norm_tot_neg_shr, norm_tot_net_shr, norm_tot_abs_shr
''' Create the Sounding (Profile) Object '''
def inis(prof, pbot=850, ptop=250, dp=-50, exact=True): ''' Formulation taken from Colquhoun and Shepherd 1989, MWR v.4 pg. 38. Calculates the sum of two components of shear over a layer, divided by the thickness of the layer. The two components are listed below: (1.) IN : The component of shear normal to the wind at the base of a given layer; relates to directional shear. (2.) IS : The component of shear in the direction of the wind at the base of a given layer; relates to speed shear. The calculation is essentially similar in concept to normalized total shear (q.v.). Parameters ---------- prof: profile object Profile object pbot : number (optional; default 850 hPa) Pressure of the bottom level (hPa) ptop : number (optional; default 250 hPa) Pressure of the top level (hPa) dp : negative integer (optional; default -50) The pressure increment for the interpolated sounding exact : bool (optional; default = True) Switch to choose between using the exact data (slower) or using interpolated sounding at 'dp' pressure levels (faster) Returns ------- inis : number INIS (number) ''' if exact: ind1 = np.where(pbot > prof.pres)[0].min() ind2 = np.where(ptop < prof.pres)[0].max() wdir1, wspd1 = interp.vec(prof, pbot) wdir2, wspd2 = interp.vec(prof, ptop) wdr = np.concatenate([[wdir1], prof.wdir[ind1:ind2+1].compressed(), [wdir2]]) wsp = np.concatenate([[wspd1], prof.wspd[ind1:ind2+1].compressed(), [wspd2]]) wsp = utils.KTS2MS(wsp) ind3 = ma.where(~prof.wspd[ind1:ind2+1].mask == True)[0] + ind1 preslvls = prof.pres[ind3] dplv = np.concatenate([[pbot - preslvls[0]], preslvls[:-1] - preslvls[1:], [preslvls[-1] - ptop]]) dpt = pbot - ptop else: ps = np.arange(pbot, ptop+dp, dp) wdr, wsp = interp.vec(prof, ps) wsp = utils.KTS2MS(wsp) dplv = np.fabs(dp) dpt = ps[0] - ps[-1] t_wdr = wdr[1:] mod = 180 - wdr[:-1] t_wdr = t_wdr + mod idx1 = ma.where(t_wdr < 0)[0] idx2 = ma.where(t_wdr >= 360)[0] t_wdr[idx1] = t_wdr[idx1] + 360 t_wdr[idx2] = t_wdr[idx2] - 360 dwdr = np.fabs(t_wdr - 180) l_in = wsp[1:] * np.sin(np.radians(dwdr)) l_is = ( wsp[1:] * np.cos(np.radians(dwdr)) ) - wsp[:-1] inis = ( ( l_in * dplv ).sum() + ( l_is * dplv ).sum() ) / ( dpt ) return inis
def append_wbz(): #Load each ERA-Interim netcdf file, and append wbz start_lat = -44.525 end_lat = -9.975 start_lon = 111.975 end_lon = 156.275 domain = [start_lat, end_lat, start_lon, end_lon] model = "erai" region = "aus" dates = [] for y in np.arange(1979, 2019): for m in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]: if (m != 12): dates.append([dt.datetime(y,m,1,0,0,0),\ dt.datetime(y,m+1,1,0,0,0)-dt.timedelta(hours = 6)]) else: dates.append([dt.datetime(y,m,1,0,0,0),\ dt.datetime(y+1,1,1,0,0,0)-dt.timedelta(hours = 6)]) for t in np.arange(0, len(dates)): print(str(dates[t][0]) + " - " + str(dates[t][1])) fname = "/g/data/eg3/ab4502/ExtremeWind/"+region+"/"+model+"/"+model+"_"+\ dt.datetime.strftime(dates[t][0],"%Y%m%d")+"_"+\ dt.datetime.strftime(dates[t][-1],"%Y%m%d")+".nc" ta,dp,hur,hgt,terrain,p,ps,wap,ua,va,uas,vas,tas,ta2d,cp,wg10,cape,lon,lat,date_list = \ read_erai(domain,dates[t]) dp = get_dp(ta, hur, dp_mask=False) agl_idx = (p <= ps) #Replace masked dp values dp = replace_dp(dp) try: prof = profile.create_profile(pres = np.insert(p[agl_idx],0,ps), \ hght = np.insert(hgt[agl_idx],0,terrain), \ tmpc = np.insert(ta[agl_idx],0,tas), \ dwpc = np.insert(dp[agl_idx],0,ta2d), \ u = np.insert(ua[agl_idx],0,uas), \ v = np.insert(va[agl_idx],0,vas), \ strictqc=False, omeg=np.insert(wap[agl_idx],0,wap[agl_idx][0]) ) except: p = p[agl_idx] ua = ua[agl_idx] va = va[agl_idx] hgt = hgt[agl_idx] ta = ta[agl_idx] \ dp = dp[agl_idx] p[0] = ps ua[0] = uas va[0] = vas hgt[0] = terrain ta[0] = tas dp[0] = ta2d prof = profile.create_profile(pres = p, \ hght = hgt, \ tmpc = ta, \ dwpc = dp, \ u = ua, \ v = va, \ strictqc=False, omeg=wap[agl_idx]) pwb0 = params.temp_lvl(prof, 0, wetbulb=True) hwb0 = interp.to_agl(prof, interp.hght(prof, pwb0)) param_file = nc.Dataset(fname, "a") wbz_var = param_file.createVariable("wbz",float,\ ("time","lat","lon")) wbz_var.units = "m" wbz_var.long_name = "wet_bulb_zero_height" wbz_var[:] = hwb0 T1 = abs( thermo.wetlift(prof.pres[0], prof.tmpc[0], 600) - interp.temp(prof, 600)) T2 = abs( thermo.wetlift(pwb0, interp.temp(prof, pwb0), sfc) - prof.tmpc[0]) Vprime = utils.KTS2MS(13 * np.sqrt((T1 + T2) / 2) + (1 / 3 * (Umean01))) Vprime_var = param_file.createVariable("Vprime",float,\ ("time","lat","lon")) Vprime_var.units = "m/s" Vprime_var.long_name = "miller_1972_wind_speed" Vprime_var[:] = Vprime param_file.close()