def derivs(t, y, entrain_rate, interpTenv, interpTdEnv, interpPress): """Function that computes derivative vector for ode integrator see http://clouds.eos.ubc.ca/~phil/courses/atsc405/docs/entrain.pdf for equations Parameters ---------- t: float time (s) y: vector 4-vector containing wvel (m/s), height (m), thetae (K), rT (kg/kg) entrain_rate: float 1/m dm/dt (s-1) interpTenv: func interp1d function for environmental temperature T(z) interpTdEnv: func interp1d function for environmental dewpoint temperature Td(z) interpPress: func interp1d function for presusure p(z) Returns ------- yp: vector 4-vector containing time derivatives of wvel (m/s^2), height (m/s), thetae (K/s), rT (kg/kg/s) """ yp = np.zeros((4,1)) velocity = y[0] height = y[1] thetae_cloud = y[2] rT_cloud = y[3] #yp[0] is the acceleration, in this case the buoyancy yp[0] = calcBuoy(height, thetae_cloud, interpTenv, interpTdEnv, interpPress) press = interpPress(height)*100. #Pa Tdenv = interpTdEnv(height) + c.Tc #K Tenv = interpTenv(height) + c.Tc #K rTenv = find_rsat(Tdenv, press) #kg/kg thetaeEnv = find_thetaep(Tdenv, Tenv, press) #yp[1] is the rate of change of height yp[1] = velocity #yp[2] is the rate of change of thetae_cloud yp[2] = entrain_rate*(thetaeEnv - thetae_cloud) #yp[3] is the rate of change of rT_cloud yp[3] = entrain_rate*(rTenv - rT_cloud) return yp
ax.plot(xcoord_T,sounding['pres'],color='k',label='temp') ax.plot(xcoord_Td,sounding['pres'],color='g',label='dew') [line.set(linewidth=3) for line in ax.lines[-2:]] out=ax.set(title=title) # In[9]: from a405thermo.thermlib import find_Tmoist,find_thetaep,find_rsat,find_Tv # # find thetae of the surface air # sfc_press,sfc_temp,sfc_td =[sounding[key][0] for key in ['pres','temp','dwpt']] sfc_press,sfc_temp,sfc_td = sfc_press*100.,sfc_temp+c.Tc,sfc_td+c.Tc sfc_rvap = find_rsat(sfc_temp,sfc_press) sfc_thetae=find_thetaep(sfc_td,sfc_temp,sfc_press) press=sounding['pres'].values*100. # # find the index for 200 hPa pressure -- searchsorted requires # the pressure array to be increasing, so flip it for the search, # then flip the index. Above 200 hPa thetae goes bananas, so # so trim so we only have # toplim=len(press) - np.searchsorted(press[::-1],2.e4) press=press[:toplim] # # find temps along that adiabat # adia_temps= np.array([find_Tmoist(sfc_thetae,the_press) for the_press in press]) adia_rvaps = find_rsat(adia_temps,press) adia_rls = sfc_rvap - adia_rvaps
pLCL = np.zeros_like(press) theTheta = np.zeros_like(press) theThetae = np.zeros_like(press) Tpseudo = np.zeros_like(press) rTotal = np.zeros_like(press) # # calculate the rTotal,thetae sounding from the original dewpoint and temperture # numPoints, = press.shape for i in range(0, numPoints): rTotal[i] = find_rsat(Tdew[i] + c.Tc, press[i] * hPa2pa) Tlcl[i], pLCL[i] = find_lcl(Tdew[i] + c.Tc, Temp[i] + c.Tc, press[i] * hPa2pa) theThetae[i] = find_thetaep(Tdew[i] + c.Tc, Temp[i] + c.Tc, press[i] * hPa2pa) #find the temperature along the pseudo adiabat at press[i] Tpseudo[i] = find_Tmoist(theThetae[i], press[i] * hPa2pa) # # given the total water and thetae, calcultate temp,dewpoint for pressure vector press # Tdew, Temp, Tpseudo = lift_sounding(rTotal,theThetae,press) fig, ax = plt.subplots(1, 1, figsize=(10, 10)) ax, skew = makeSkewWet(ax,corners=[5,25]) fig_dict=dict(press=press,Tpseudo=Tpseudo,Temp=Temp,Tdew=Tdew,Tlcl=Tlcl,pLCL=pLCL,botLabel='LCL bot (835 hPa)', topLabel='LCL top (768 hPa)') ax = makePlot(ax,**fig_dict)
ax.plot(xcoord_T,sounding['pres'],color='k',label='temp') ax.plot(xcoord_Td,sounding['pres'],color='g',label='dew') [line.set(linewidth=3) for line in ax.lines[-2:]] out=ax.set(title=title) # In[5]: from a405thermo.thermlib import find_Tmoist,find_thetaep,find_rsat,find_Tv # # find thetae of the surface air # sfc_press,sfc_temp,sfc_Td =[sounding[key][0] for key in ['pres','temp','dwpt']] sfc_press,sfc_temp,sfc_Td = sfc_press*100.,sfc_temp+c.Tc,sfc_Td+c.Tc sfc_rvap = find_rsat(sfc_Td,sfc_press) sfc_thetae=find_thetaep(sfc_Td,sfc_temp,sfc_press) press=sounding['pres'].values*100. # # find the index for 200 hPa pressure -- searchsorted requires # the pressure array to be increasing, so flip it for the search, # then flip the index. Above 100 hPa thetae goes bananas, so # so trim so we only have # toplim=len(press) - np.searchsorted(press[::-1],1.5e4) clipped_press=press[:toplim] # # find temps along that adiabat # adia_temps= np.array([find_Tmoist(sfc_thetae,the_press) for the_press in clipped_press]) adia_rvaps = find_rsat(adia_temps,clipped_press) adia_rls = sfc_rvap - adia_rvaps
def integ_entrain(df_sounding,entrain_rate): """integrate an ascending parcel given a constant entrainment rate this version hardwired to start parcel at 800 hPa with cloud base values of environment at 900 hPa Parameters ---------- df_sounding: pandas dataframe : cloumns are temperature, dewpoint, height, press entrain_rate: float 1/m dm/dt (s-1) Returns ------- df_out: dataframe dataframe containing wvel (m/s) ,cloud_height (m) , thetae (K), rT (kg/kg) for assending parcel interpPress: func interp1d function for presusure p(z) (used for plotting) """ press = df_sounding['pres'].values height = df_sounding['hght'].values temp = df_sounding['temp'].values dewpoint = df_sounding['dwpt'].values envHeight= nudge(height) interpTenv = interp1d(envHeight,temp) interpTdEnv = interp1d(envHeight,dewpoint) interpPress = interp1d(envHeight,press) # # call this cloudbase # p900_level = len(press) - np.searchsorted(press[::-1],900.) thetaeVal=find_thetaep(dewpoint[p900_level] + c.Tc,temp[p900_level] + c.Tc,press[p900_level]*100.) rTcloud = find_rsat(dewpoint[p900_level] + c.Tc, press[p900_level]*100.) # # start parcel here # p800_level = len(press) - np.searchsorted(press[::-1],800.) height_800=height[p800_level] winit = 0.5 #initial velocity (m/s) yinit = [winit, height_800, thetaeVal, rTcloud] tinit = 0 #seconds tfin = 2500 #seconds dt = 10 #seconds #want to integrate derivs using dopr15 runge kutta described at # http://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.ode.html # r = ode(derivs).set_integrator('dopri5') r.set_f_params(entrain_rate, interpTenv, interpTdEnv, interpPress) r.set_initial_value(yinit, tinit) #the while loop below integrates every dt seconds #we stop tracking the parcel when the time runs out, or if the parcel stops moving/is desecnding # var_out = [] time_out =[] while r.successful() and r.t < tfin and r.y[0] > 0: #find y at the next time step #(r.integrate(t) updates the fields r.y and r.t so that r.y = integral of derivs(t) and r.t = time #where derivs is a vector with the variables to be integrated # # move ahead by dt # r.integrate(r.t+dt) # # stop if there is negative vertical velocity # if r.y[0] <= 0: break # #save values for dataframe # var_out.append(r.y) time_out.append(r.t) # # convert the output into a datafram # colnames=['wvel','cloud_height','thetae_cloud','rT_cloud'] df_out=pd.DataFrame.from_records(var_out,columns=colnames) df_out['time'] = time_out return df_out,interpPress