def find_Tmoist(thetaE0, press): """ Calculates the temperatures along a moist adiabat. Parameters ---------- thetaE0 : float Initial equivalent potential temperature (K). press : float or array_like Pressure (Pa). Returns ------- Temp : float or array_like Temperature (K) of thetaE0 adiabat at 'press'. Examples -------- >>> np.array([find_Tmoist(300., 8.e4)]) array([ 271.0638]) >>> find_Tmoist(330., 8.e4) 283.7226584032411 """ Tstart = c.Tc try: brackets = rf.find_interval(thetaes_diff, Tstart, thetaE0, press) Temp = rf.fzero(thetaes_diff, brackets, thetaE0, press) except BracketError as e: print("couldn't find bracket: debug info: ",e.extra_info) Temp = np.nan return Temp
def find_Tmoist(thetaE0, press): """ Calculates the temperatures along a moist adiabat. Parameters ---------- thetaE0 : float Initial equivalent potential temperature (K). press : float or array_like Pressure (Pa). Returns ------- Temp : float or array_like Temperature (K) of thetaE0 adiabat at 'press'. Examples -------- >>> find_Tmoist(300., 8.e4) 270.59590841970277 >>> find_Tmoist(330., 800) 290.98965468303 """ Tstart=c.Tc brackets=rf.find_interval(thetaes_diff,Tstart,thetaE0,press) Temp = rf.fzero(thetaes_diff,brackets,thetaE0,press) return Temp
def temp_from_theta(theta,press): """ input: theta (K), press (Pa) output: temp (K) found by rootfinder """ # # use theta as guess for bracket and pass theta,press to theta_zero # brackets=rf.find_interval(theta_zero,theta,theta,press) the_temp = rf.fzero(theta_zero,brackets,theta,press) return the_temp
def tinvert_thetae(thetaeVal, rT, press): """ temp,rv,rl=tinvert_thetae(thetaeVal, rT, press) Uses a rootfinder to determine the temperature for which the pseudo equivilant potential temperature (thetaepress) is equal to the equivilant potential temperature (thetae) of the parcel. Parameters ---------- thetaeVal : float Thetae of parcel (K). rT : float Total water mixing ratio (kg/kg). press : float Pressure of parcel in (Pa). Returns ------- theTemp : float Temperature for which thetaep equals the parcel thetae (K). rv : float Vapor mixing ratio of the parcel (kg/kg). rl : float liquid water mixing ratio of the parcel (kg/kg) at 'press'. Raises ------ IOError If 'press' is larger than 100000 Pa. Examples -------- >>> tinvert_thetae(300., 0.001, 8.e4) (278.4050485684102, 0.001, 0) """ if press > 1.e5: raise IOError('expecting pressure level less than 100000 Pa') # The temperature has to be somewhere between thetae # (T at surface) and -40 deg. C (no ice). Tstart = c.Tc brackets = rf.find_interval(find_resid_thetae, Tstart, thetaeVal, rT, press) theTemp = rf.fzero(find_resid_thetae, brackets, thetaeVal, rT, press) rv, rl = find_rvrl(theTemp, rT, press) return theTemp, rv, rl
def tinvert_rsat(Tstart,rsat,press): """ rootfind the temp that produces rsat at press. Parameters ---------- temp : float temperature (K) rsat : float saturation mixing ratio (kg/kg) press : float pressure (hPa) Returns ------- Tdew : temperature (K) at with air is saaturated """ brackets=rf.find_interval(find_resid_rsat,Tstart,rsat,press) temp = rf.fzero(find_resid_rsat,brackets,rsat,press) return temp
cloud_vars['koehler_fun'] = koehler_fun # ### find the equilibrium radius for each bin at saturation Sinit # In[41]: S_target = parcel.Sinit logr_start = np.log(0.1e-6) initial_radius = [] dry_radius = [] for mass in center_mass: brackets = np.array(find_interval(find_diff,logr_start,S_target,mass,koehler_fun)) left_bracket, right_bracket = np.exp(brackets)*1.e6 #get brackets in microns for printing equil_rad = np.exp(fzero(find_diff,brackets,S_target,mass,koehler_fun)) initial_radius.append(equil_rad) dry_rad = (mass/(4./3.*np.pi*aero.rhoaero))**(1./3.) dry_radius.append(dry_rad) print('mass = {mass:6.3g} kg'.format_map(locals())) print('equlibrium radius at S={} is {:5.3f} microns\n'.format(S_target,equil_rad*1.e6)) # ### now add the intial conditions to the cloud_vars dictionary and make it a namedtuple # # the vector var_vec holds 30 droplet radii plus three extra variables at the # end of the vector: the temperature, pressure and height. # In[42]:
matplotlib.style.use('ggplot') fig,ax = plt.subplots(1,1) rvals=np.linspace(0.05,0.3,50)*1.e-6 Svals = find_S(rvals) ax.plot(rvals*1.e6,(Svals -1)*1.e2) out=ax.set(ylim=[-1,1],xlim = [0.05,0.3], ylabel='Supersaturation (e/es - 1) %',xlabel='radius (microns)') # ### 2. Find haze particle equilibrium radius at S=0.9 # In[21]: def find_diff(r,S_target): return S_target - find_S(r) S_target = 0.90 r_start = 0.1e-6 from a405thermo.rootfinder import find_interval, fzero brackets = np.array(find_interval(find_diff,r_start,S_target)) print('left bracket = {:8.3e} microns, right bracket={:8.3e} microns'.format(*(brackets*1.e6))) equil_rad = fzero(find_diff,brackets,S_target) print('equlibrium radius at S={} is {:5.3f} microns'.format(S_target,equil_rad*1.e6)) # In[ ]:
print(help(rf.find_interval)) # ### example -- find a bracket for sin(x)=0 near x=12 radians ~ 700 degrees # In[8]: brackets=rf.find_interval(np.sin,12) brackets # ## now use the fzero wrapper to find the root of sin(x)=0 (720 degrees) # In[9]: print(rf.fzero(np.sin,brackets)*180/np.pi) # ## Redo theta example with find_interval # In[39]: import a405thermo.rootfinder as rf from importlib import reload reload(rf) def theta_zero(Tguess,theta,press): """Function we want to find the root of input: Tguess (K), target theta (K), press (Pa) output: difference between guess and target -- should be zero when x is a root """
def zero_find_es(temp): esguess=standard_es(temp) brackets=rf.find_interval(zero_es,esguess,temp) resid = rf.fzero(zero_es,brackets,temp) return resid
def find_diff(logr,S_target,m): """ zero function for rootfinder """ r = np.exp(logr) return S_target - koehler_fun(r,m) S_target = parcel.Sinit logr_start = np.log(0.1e-6) initial_radius = [] for mass in center_mass: brackets = np.array(find_interval(find_diff,logr_start,S_target,mass)) left_bracket, right_bracket = np.exp(brackets)*1.e6 #get brackets in microns for printing equil_rad = np.exp(fzero(find_diff,brackets,S_target,mass)) Scrit=(4.*a**3./(27.*b*mass))**0.5 initial_radius.append(equil_rad) print(('mass = {mass:6.3g} kg\n' 'left bracket = {left_bracket:8.3e} microns\n' 'right bracket={right_bracket:8.3e} microns\n' 'critical supersaturation: {Scrit:6.3g}') .format_map(locals())) print('equlibrium radius at S={} is {:5.3f} microns\n'.format(S_target,equil_rad*1.e6)) # In[ ]:
# In[4]: def rv_diff(press,thetae_mix,rT_mix): """ the lcl is is the pressure where rv=rT_mix we want a difference that changes sign at cloud base so below cloud set rv = rsat(temp,press) and rT_mix - rv will be negative below cloud base and positive above cloud base """ Temp, rv, rl = tinvert_thetae(thetae_mix,rT_mix,press) # # below cloud rl ~ 0, so switch to rv=rsat # if rl < 1.e-5: rv=find_rsat(Temp,press) diff = rT_mix - rv return diff from a405thermo.rootfinder import find_interval,fzero bracket=find_interval(rv_diff,7.e4,thetae_mix,rt_mix) print('found bracket =',bracket) lcl_press=fzero(rv_diff,bracket,thetae_mix,rt_mix) print('the lcl pressure is {} hPa'.format(n(lcl_press*1.e-2))) # In[ ]: