def diffusion(diff_time=12.0, namelist=False, inverse=False): """ Compute arrays of diffusion co-efficients for all levels. :param diff_time: time in hours for diffusion :param inverse: optional -- default = False. invert relationship to work our diffusion time :param namelist: default False. If True return only the namelist information. :return: if inverse set compute diffusion timescale otherwise compute diffusion coefficients. returns them as a dict with entries diff_coeff -- diffusion coefficient, diff_coeff_q -- diffusion coefficient for water vapour diff_power -- power of diffusion, diff_power_q -- power for diffusion. """ # TODO -- if necessary allow levels to be specified or read from namelists. Also read other info on model! # NAMELIST information. diff_coeff_nl = _namedTupClass(var='DIFF_COEFF', namelist='RUNCNST', file='CNTLATM') diff_coeff_q_nl = _namedTupClass(var='DIFF_COEFF_Q', namelist='RUNCNST', file='CNTLATM') diff_exp_nl = _namedTupClass(var='DIFF_EXP', namelist='RUNCNST', file='CNTLATM') diff_exp_q_nl = _namedTupClass(var='DIFF_EXP_Q', namelist='RUNCNST', file='CNTLATM') if namelist: return [diff_coeff_nl, diff_coeff_q_nl, diff_exp_nl, diff_exp_q_nl] elif inverse: powerDiff = diff_time[diff_exp_nl][0] * 2 diff_time_hrs = diff_fn(diff_time[diff_coeff_nl][0], dyndel=powerDiff, inverse=inverse) return diff_time_hrs else: diff_coeff, diff_coeff_q, diff_exp, diff_exp_q = \ metaDIFFS(dyndiff=diff_time, dyndel=diff_pwr) return {diff_coeff_nl: diff_coeff, diff_coeff_q_nl: diff_coeff_q, diff_exp_nl: diff_exp, diff_exp_q_nl: diff_exp_q}
def cloudEACF( eacf=0.5, inverse=False, namelist=False): """ Compute array of eacf values for each model level. If inverse set work out what meta-parameter is from array. :param eacf: meta-pramater value for eacf :param inverse: compute inverse relationship :param namelist: default False. If True return only the namelist information. :return: either a dict with cloud_eacf being a list of values on each level. """ # TODO if necessary -- allow number of levels to be specified or at least pull out of the model. eacf_nl = _namedTupClass(var='EACF', namelist='SLBC21', file='CNTLATM') if namelist: return [eacf_nl] elif inverse: return eacf[eacf_nl][0] else: assert eacf >= 0.5, "eacf seed must be ge 0.5, according to R code but it is %f\n" % eacf eacfbl = [0.5, 0.7, 0.8] eacftrp = [0.5, 0.6, 0.65] five = 5 * [eacf] eacf1 = IDLinterpol(eacftrp, eacfbl, eacf) cloud_eacf = 19 * [eacf1] cloud_eacf[0:5] = five cloud_eacf[5] = (2. * eacf + eacf1) / 3. cloud_eacf[6] = (eacf + 2. * eacf1) / 3. return {eacf_nl: cloud_eacf}
def runTarget(target=[0,0,0], inverse=False,namelist=False): """ :param target: run target time as [YYYY, MM, DD, HH, MM, SS] as used by the UM. If list contains less than 6 elements then remaining values are set to 0. :param inverse: Do inverse calculation and return 6 element list as [YYYY, MM, DD, HH, MM, SS] :param namelist: Do no computation just return the namelist info :return: namelist info and values as array. (or if inverse set return the run target ) """ # verify that len of target is >= 3 and <= 6 and if not raise error. if not (1 <= len(target) <=6) : raise Exception("target should have at >= 1 members and <= 6") # set up all the var/namelist/file info. namelistData=[_namedTupClass(var='RUN_TARGET_END',namelist=nl,file=file) for file,nl in zip(['CNTLALL','CONTCNTL','RECONA','SIZES'], ['NLSTCALL','NLSTCALL','STSHCOMP','STSHCOMP'])] if namelist: return namelistData # return the namelist info elif inverse: return target[namelistData[0]] # jsut return the value else: tgt=target[:] tgt.extend([0]*(len(tgt)-6)) # add trailing zeros result={nl:tgt for nl in namelistData} return result # return the namelist info.
def startTime(time=[1965, 7, 4] ,inverse=False, namelist=False): """ :param time: start time as 3 to 6 element list. Spcifiying in order year, month, day of month, hour, minute and second if hour, minute and second not specified they are set to zero. :param inverse: Do inverse calculation and return 6 element list as [YYYY, MM, DD, HH, MM, SS] :param namelist: No computation just return the namelist info. :return: namelist info and values as array. (or if inverse set return the start time) Need to set MODEL_BASIS_TIME in CNTLALL/&NLSTCALL & CONTCNTL/&NLSTCALL but only the year part -- which reguires something clever. No make the specifiy the basis_time and then write it out. fixhd(21) & fixhd(28) in RECONA/&HEADERS -- this resets the year. (Presumably we could reset the month etc too.) Just need to reset year => adding to tupple an indicator for which part of an array to change?? (Breaks existing stuff?) ALas f90nml patch seems to fail for RECONA so will need to write it out explicitly. """ # verify that len of target is >= 3 and <= 6 and if not raise error. if not (1 <= len(time) <= 6): raise Exception("start time should have at >= 1 members and <= 6") # set up all the var/namelist/file info. namelistData = [_namedTupClass(var='MODEL_BASIS_TIME', namelist=nl, file=file) for file, nl in zip(['CNTLALL', 'CONTCNTL'], ['NLSTCALL', 'NLSTCALL'])] if namelist: return namelistData # return the namelist info elif inverse: return time[namelistData[0]] # jsut return the value else: t = time[:] t.extend([0] * (len(t) - 6)) # add trailing zeros result = {nl: t for nl in namelistData} return result # return the namelist info.
def cloudWater( cw_land=2e-4, inverse=False, namelist=False): """ Compute cw_sea from cw_land :param cw_land: value of cw_land :param inverse -- if true do inverse calculation and return cw_land :return: returns dict containing cloud_cw_land and cloud_cw_sea values. """ cw_land_nl = _namedTupClass(var='CW_LAND', namelist='RUNCNST', file='CNTLATM') cw_sea_nl = _namedTupClass(var='CW_SEA', namelist='RUNCNST', file='CNTLATM') if namelist: return [cw_land_nl, cw_sea_nl] elif inverse: return cw_land[cw_land_nl] else: cwl = [1e-04, 2e-04, 2e-03] cws = [2e-05, 5e-05, 5e-04] cw_sea = IDLinterpol(cws, cwl, cw_land) return {cw_land_nl: cw_land, cw_sea_nl: cw_sea}
def iceAlbedo( alpham=0.5, inverse=False, namelist=False): """ Compute ice albedo values given alpham :param alpham: value of alpham (if forward) or dict containing parameters for inverse :param inverse: default is False -- compute alpham :param namelist -- return namelist used. :return: """ # namelist information alpham_nl = _namedTupClass(var='ALPHAM', namelist='RUNCNST', file='CNTLATM') dtice_nl = _namedTupClass(var='DTICE', namelist='RUNCNST', file='CNTLATM') if namelist: return [alpham_nl, dtice_nl] elif inverse: return alpham[alpham_nl] else: mins = [0.5, 0.57, 0.65] # alpham values maxs = [10., 5., 2.] # corresponding dtice values dtice = IDLinterpol(maxs, mins, alpham) # from Mike's code. return {dtice_nl: dtice, alpham_nl: alpham}
def gravityWave(kay=2e4, inverse=False, namelist=False): """ Compute gravity wave parameters given kay parameter. :param kay: value of kay (default is 2x10^4) :param inverse: invert calculation :param namelist: return the namelist used and do no computation. :return: dict containing kay_gwave and kay_lee_gwave parameters. (or value of kay if inverse set) """ # name list info gwave = _namedTupClass(var='KAY_GWAVE', namelist='RUNCNST', file='CNTLATM') lee_gwave = _namedTupClass(var='KAY_LEE_GWAVE', namelist='RUNCNST', file='CNTLATM') if namelist: return [gwave, lee_gwave] # return the namelist only # do the computations. elif inverse: return kay[gwave] # extract kay from the info. else: # from MIke's code (in turn from R code) gwd_pt = [1e04, 1.5e04, 2e04] lee_pt = [1.5e05, 2.25e05, 3e05] lee = IDLinterpol(lee_pt, gwd_pt, kay) return {gwave: kay, lee_gwave: lee}
def runName( name='abcdz', inverse=False, namelist=False): """ Compute experiment and job id. :param name: 5-character UM name :param inverse: Default value False. If True compute name from input directory. :param namelist: return the namelist used and do no computation. :return: experiment and job id from name or name from name['experID']+name['jobID']+name """ # make namelist information. jobname_nl =_namedTupClass(var='RUN_JOB_NAME', namelist='NLCHISTO', file='INITHIS') exper_nl = _namedTupClass(var='EXPT_ID', namelist='NLSTCALL', file='CNTLALL') jobid_nl = _namedTupClass(var='JOB_ID', namelist='NLSTCALL', file='CNTLALL') exper2_nl =_namedTupClass(var='EXPT_ID', namelist='NLSTCALL', file='CONTCNTL') jobid2_nl = _namedTupClass(var='JOB_ID', namelist='NLSTCALL', file='CONTCNTL') if namelist: return [jobname_nl, exper_nl, jobid_nl, exper2_nl, jobid2_nl] elif inverse: return name[exper_nl] + name[jobid_nl] # wrap experID & jobID to make name else: sname=str(name) # convert to string return {exper_nl: sname[0:4], jobid_nl: sname[4], exper2_nl: sname[0:4], jobid2_nl: sname[4], jobname_nl: sname + "000"} # split name to make experID, jobID and jobnaame
def sph_ice(sphIce=True,inverse=False,namelist=False): """ Setup namelist for non-spherical ice. :param sphIce: True if want spherical ice (which is default) :param inverse: Return (from namelists) if spherical ice. :param namelist: Return namelist info :return: returns values or namelist. """ nl=[_namedTupClass(var='I_CNV_ICE_LW',namelist='R2LWCLNL',file='CNTLATM'), # default 1, perturb 7 _namedTupClass(var='I_ST_ICE_LW', namelist='R2LWCLNL', file='CNTLATM'), # default 1, perturb 7 _namedTupClass(var='I_CNV_ICE_SW', namelist='R2SWCLNL', file='CNTLATM'),# defaault 3, perturb 7 _namedTupClass(var='I_ST_ICE_SW', namelist='R2SWCLNL', file='CNTLATM'), # default 2, perturb 7 ] values_sph=[1,1,3,2] values_nonSph=[7,7,7,7] if namelist: # just return the namelist info return nl elif inverse: # inverse -- so extract value and test for consistency # check all is OK sph=sphIce[nl[0]] == 1 if sph: values=values_sph else: values=values_nonSph for n,v in zip(nl,values): if sphIce[n] != v: raise Exception("Got %d when expected %d"%(sphIce[n],v)) return sph else: # setting values if sphIce: values=values_sph else: values=values_nonSph result={n:v for n,v in zip(nl,values)} # return namelist info. return result
def initHist_nlcfiles(value='NoSuchFile.txt', inverse=False, namelist=False, parameter=None): """ :param value: value to be set -- typically the name of a file :param parameter: string for parameter -- must be provided. :param inverse: inverst string (remove bit before the : and return the string after that. ) :return:string (or inverse) to return. """ nl=_namedTupClass(var=parameter, namelist='NLCFILES', file='INITHIS') if namelist: return [nl] if inverse: return value[nl].split(':')[1].lstrip() # extract value from passed in name list removing space when doing so. else: # need to generate 8 blanks then fill in with parameter. st="%-8.8s: %s"%(parameter,value) # Alas HadCM3 lives in the 8 character MSDOS world... I wonder why that limit chosen? return {nl:st}
def cloudRHcrit(rhcrit=0.7, inverse=False, namelist=False): """ Compute rhcrit on multiple model levels :param rhcrit: meta parameter for rhcrit :param inverse: default False. If True invert the relationship :param namelist: default False. If True return only the namelist information. :return: (value of meta parameter if inverse set otherwise a dict with cloud_rh_crit containing a list of rh_crit on model levels """ # TODO if necessary -- allow number of levels to be specified?? rhcrit_nl = _namedTupClass(var='RHCRIT', namelist='RUNCNST', file='CNTLATM') if namelist: return {rhcrit_nl: None} elif inverse: return rhcrit[rhcrit_nl][3] else: cloud_rh_crit = 19 * [rhcrit] cloud_rh_crit[0] = max(0.95, rhcrit) cloud_rh_crit[1] = max(0.9, rhcrit) cloud_rh_crit[2] = max(0.85, rhcrit) return {rhcrit_nl: cloud_rh_crit}