def calc_enthalpy(point_dict): """ Calculate the enthalpy and total water mixing ratio for an air parcel, given a dictionary or parameters Parameters ---------- point_dict: dictionary dictionary with the following keys ['id','temp','rv','rl','press'] units: point letter, K kg/kg kg/kg Pa Returns ------- vals: named tuple tuple with dictionary values plus rt (kg/kg) and enthalpy (J/kg) """ point_dict['rt'] = point_dict['rv'] + point_dict['rl'] vals = make_tuple(point_dict) cp = c.cpd + vals.rt*c.cl point_dict['enthalpy'] = cp*vals.temp + find_lv(vals.temp)*vals.rv vals = make_tuple(point_dict) return vals
def find_interval(the_func, x, *args): """ starting from a 2% difference, move out from a point until the_func changes sign Parameters ---------- the_func : function function that returns zero when on root x : float argument to the_func *args : tuple additional arguments for the_func Returns ------- brackets : [left,right] left,right brackets for root """ if x == 0.0: dx = 1.0 / 50.0 else: dx = x / 50.0 maxiter = 40 twosqrt = np.sqrt(2) failed = True for i in range(maxiter): dx = dx * twosqrt a = x - dx fa = the_func(a, *args) b = x + dx fb = the_func(b, *args) if fa * fb < 0.0: failed = False break if failed: # # load the debugging information into the BracketError exception as a # namedtuple # extra_info = make_tuple(dict(a=a, b=b, fa=fa, fb=fb, x=x, dx=dx, args=args)) raise BracketError("Couldn't find a suitable range. Providing extra_info", extra_info=extra_info) return (a, b)
import pandas as pd from matplotlib import pyplot as plt import datetime, h5py # ### Read in the yaml file and set the koehler function for this aerosol # In[39]: util_dir = a405utils.__path__[0] data_dir = Path(util_dir).joinpath('../data') yaml_file = data_dir.joinpath('dropgrow.yaml') with yaml_file.open('r') as f: input_dict=ry.load(f,Loader=ry.RoundTripLoader) aero=make_tuple(input_dict['aerosol']) parcel=make_tuple(input_dict['initial_conditions']) koehler_fun = create_koehler(aero,parcel) # ### initialize the lognormal mass and number distributions for 30 bins # In[40]: # #set the edges of the mass bins #31 edges means we have 30 droplet bins # numrads = 30
g = make_format() info = make_format(format_string="debugging {}") a=10 b=1.546e-23 print(info(a), g(b)) # ### Calculating the equilibrium size distribution for unactivated aerosols # # Below we use the rootfinder to search on log(radius) to find the equilibrium # drop size for unactivaed aerosols on the left side of their Koehler curves # In[55]: aero=make_tuple(input_dict['aerosol']) parcel=make_tuple(input_dict['initial_conditions']) a, b = find_koehler_coeffs(aero,parcel) # # sanity check # m=1.e-18 Scrit=(4.*a**3./(27.*b*m))**0.5; rcrit = (3.*m*b/a)**0.5 print(("for aerosol with mass = {} kg, " "SScrit,rcrit are {:8.3g}, {:8.3g} microns") .format(m,Scrit,rcrit*1.e6))
mass_vals = np.linspace(-20, -16, numrads + 1) mass_vals = 10 ** mass_vals mu = input_dict["aerosol"]["themean"] sigma = input_dict["aerosol"]["sd"] totmass = input_dict["aerosol"]["totmass"] mdist = totmass * lognormal(mass_vals, np.log(mu), np.log(sigma)) mdist = find_centers(mdist) * np.diff(mass_vals) center_mass = find_centers(mass_vals) ndist = mdist / center_mass cloud_vars = od() cloud_vars["mdist"] = mdist cloud_vars["ndist"] = ndist cloud_vars["center_mass"] = center_mass aero = make_tuple(input_dict["aerosol"]) parcel = make_tuple(input_dict["initial_conditions"]) koehler_fun = create_koehler(aero, parcel) 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.0e6 # get brackets in microns for printing equil_rad = np.exp(fzero(find_diff, brackets, S_target, mass, koehler_fun)) initial_radius.append(equil_rad)