def arctic_seb(xml, seb_new=False): if seb_new: for name in [ 'snow-source_sink', 'snow_column:*-source_sink', 'water_source', 'column:*-water_source' ]: try: # check for water source asearch.find_path(xml, ['state', 'field evaluators', name]) except aerrors.MissingXMLError: pass else: seb_threecomponent(xml, name) create_landcover(xml, name, 0.002) else: for name in [ 'snow-source_sink', 'snow_column:*-source_sink', 'water_source', 'column:*-water_source' ]: try: # check for water source asearch.find_path(xml, ['state', 'field evaluators', name]) except aerrors.MissingXMLError: pass else: seb_twocomponent(xml, name) create_landcover(xml, name, 0.02)
def seb_threecomponent(xml, eval_name): """This changes the old, 'Arctic' SEB model into more robust variant that crashes less often.""" # area fractions try: frac_area = asearch.find_path( xml, ["state", "field evaluators", "snow-fractional_areas"]) except aerrors.MissingXMLError: pass else: frac_area.setName("surface-fractional_areas") for name in [ 'surface-fractional_areas', 'surface_column:*-fractional_areas' ]: try: frac_area = asearch.find_path(xml, ["state", "field evaluators", name]) except aerrors.MissingXMLError: pass else: domain = frac_area.getName().split('-')[0] frac_area.setName(domain + "-area_fractions") frac_area_type = asearch.child_by_name(frac_area, "field evaluator type") if frac_area_type.getValue() == "surface balance area fractions": frac_area_type.setValue("area fractions, three components") # water source try: water_source = asearch.find_path( xml, ['state', 'field evaluators', eval_name]) except aerrors.MissingXMLError: pass else: water_source_type = asearch.child_by_name(water_source, "field evaluator type") if water_source_type.getValue() == "surface balance": water_source_type.setValue( "surface energy balance, three components") # subgrid albedos for name in [ 'surface-subgrid_albedos', 'surface_column:*-subgrid_albedos' ]: try: albedo = asearch.find_path(xml, ['state', 'field evaluators', name]) except aerrors.MissingXMLError: pass else: dname = name.split('-')[0] albedo.setName(dname + '-albedos') albedo_type = asearch.child_by_name(albedo, "field evaluator type") if albedo_type.getValue() == "albedo": albedo_type.setValue("three-component subgrid albedos")
def add_to_lc(eval_name, param_name, param_default, lc, param_name_new=None): if param_name_new is None: param_name_new = param_name # add the dessicated zone thickness try: evaluator = asearch.find_path( xml, ['state', 'field evaluators', eval_name]) except aerrors.MissingXMLError: pval = None else: try: param = asearch.child_by_name(evaluator, param_name) except aerrors.MissingXMLError: pval = None else: pval = param.getValue() evaluator.remove(param) if pval is None: pval = param_default lc.append(parameter.DoubleParameter(param_name_new, pval))
def priestley_taylor(xml): eval_list = asearch.find_path(xml, ['state', 'field evaluators']) for ev in eval_list: ev_type = asearch.child_by_name(ev, 'field evaluator type') if ev_type.getValue() == 'potential evapotranspiration': ev_type.setValue('potential evapotranspiration, Priestley-Taylor') # net radiation is the new key, old used shortwave by default default = True try: sw_key = asearch.child_by_name(ev, 'shortwave radiation key') except aerrors.MissingXMLError: pass else: sw_key.setName('net radiation key') default = False try: sw_suffix = asearch.child_by_name( ev, 'shortwave radiation key suffix') except aerrors.MissingXMLError: pass else: sw_key.setName('net radiation key suffix') default = False if default: ev.append( parameter.StringParameter('net radiation key suffix', 'shortwave_radiation')) if ev.getName() == 'surface-air_temperature_inter': # this name is dead, now just surface-temperature (which is what it was intended to be physically) ev.setName('surface-temperature')
def fixOverlandConductivity(xml): pm = asearch.parent_map(xml) fe = asearch.find_path(xml, ["state", "field evaluators"]) try: elev = asearch.find_name(xml, "elevation evaluator") except aerrors.MissingXMLError: pass else: pk = pm[elev] pk.remove(elev) domain_name = pk.getElement("domain name").getValue() elev.setName(domain_name + "-elevation") if elev.isElement("elevation function"): elev.setParameter("field evaluator type", "string", "standalone elevation") for comp in asearch.findall_name(elev, "components"): comp.setValue(["cell", "face"]) else: elev.setParameter("field evaluator type", "string", "meshed elevation") fe.append(elev) try: oc = asearch.find_name(xml, "overland conductivity evaluator") except aerrors.MissingXMLError: pass else: pk = pm[oc] pk.remove(oc) domain_name = pk.getElement("domain name").getValue() oc.setName(domain_name + "-overland_conductivity") oc.setParameter("field evaluator type", "string", "overland conductivity") fe.append(oc)
def fixSnow(xml): # remove "include dt factor" # rename "dt factor" --> "dt factor [s]" try: snow_cond = asearch.find_path( xml, ["state", "field evaluators", "snow-conductivity"]) except aerrors.MissingXMLError: pass else: try: snow_cond.pop("include dt factor") except aerrors.MissingXMLError: pass try: dtf = asearch.find_name(snow_cond, "dt factor") except aerrors.MissingXMLError: pass else: dtf.setName("dt factor [s]") # rename "include density factor" --> "include density" try: inc_dens = asearch.find_name(snow_cond, "include density factor") except aerrors.MissingXMLError: pass else: inc_dens.setName("include density") # add "swe density factor [-]" (default is 10) if len(asearch.findall_name(snow_cond, "swe density factor [-]")) == 0: snow_cond.append( parameter.DoubleParameter("swe density factor [-]", 10.0))
def fixEvaluator(xml, name, newname): try: pd = asearch.find_path(xml, ["state", "field evaluators", name]) except aerrors.MissingXMLError: pass else: pd.setName(newname)
def end_time_units(xml): """yr --> y""" try: end_time = asearch.find_path(xml, ["cycle driver", "end time units"]) except aerrors.MissingXMLError: pass else: if end_time.getValue() == "yr": end_time.setValue("y")
def bad_spinup_longwave(xml): """One spinup file commonly used includes a longwave radiation value that is totally wrong. Not many runs actually used it. Some runs even had a spec for it in their file, but didn't include the necessary flag to use it. So this just removes it to avoid confusion.""" evals = asearch.find_path(xml, ["state","field evaluators"]) try: lw = evals.getElement("surface-incoming_longwave_radiation") except aerrors.MissingXMLError: pass else: try: filename = asearch.find_path(lw, ["function","domain","function","function-tabular","file"]) except aerrors.MissingXMLError: pass else: if "spinup-10yr.h5" in filename.getValue(): evals.pop("surface-incoming_longwave_radiation")
def create_landcover(xml, eval_name='water_source', water_transition_depth=0.02): """Adds a default land-cover section that will be the same as the Arctic defaults.""" ic_list = asearch.find_path(xml, ['state', 'initial conditions']) try: lc = asearch.child_by_name(ic_list, "land cover types") except aerrors.MissingXMLError: pass else: return # already exists # create a single land-cover type on the entire surface domain def add_to_lc(eval_name, param_name, param_default, lc, param_name_new=None): if param_name_new is None: param_name_new = param_name # add the dessicated zone thickness try: evaluator = asearch.find_path( xml, ['state', 'field evaluators', eval_name]) except aerrors.MissingXMLError: pval = None else: try: param = asearch.child_by_name(evaluator, param_name) except aerrors.MissingXMLError: pval = None else: pval = param.getValue() evaluator.remove(param) if pval is None: pval = param_default lc.append(parameter.DoubleParameter(param_name_new, pval)) lc = ic_list.sublist('land cover types').sublist('surface domain') add_to_lc('water_source', 'dessicated zone thickness [m]', 0.1, lc) add_to_lc('water_source', 'roughness length of bare ground [m]', 0.04, lc) add_to_lc('water_source', 'roughness length of snow-covered ground [m]', 0.004, lc, 'roughness length of snow [m]') add_to_lc('water_source', 'snow-ground transitional depth [m]', 0.02, lc, 'snow transition depth [m]') add_to_lc('water_source', 'water-ground transitional depth [m]', water_transition_depth, lc, 'water transition depth [m]') add_to_lc('surface-subgrid_albedos', 'albedo ground surface [-]', 0.135, lc, 'albedo of bare ground [-]') add_to_lc('surface-subgrid_albedos', 'emissivity tundra [-]', 0.92, lc, 'emissivity of bare ground [-]')
def alias_mesh_target(xml): mesh_list = asearch.child_by_name(xml, "mesh") for mesh in mesh_list: mtype = asearch.child_by_name(mesh, "mesh type") if mtype.getValue() == "aliased": try: alias = asearch.find_path(mesh, ["aliased parameters", "alias"]) except aerrors.MissingXMLError: pass else: alias.setName("target")
def getCoordinateFromList(self, one_list): well_name = one_list.getElement("Region").value region = search.child_by_name( search.find_path(self.xml, [ "amanzi_input", "regions", ], False), well_name) try: coordinate = region.get("coordinate") except KeyError: raise RuntimeError("Region is not of type point") return coordinate
def snow_distribution(xml): try: snow_dist_pk = asearch.find_path(xml, ["PKs","snow distribution"]) except aerrors.MissingXMLError: pass else: if snow_dist_pk.isElement("primary variable key") and \ asearch.child_by_name(snow_dist_pk,"primary variable key").getValue() == "surface-precipitation_snow": asearch.child_by_name(snow_dist_pk,"primary variable key").setValue("snow-precipitation") if snow_dist_pk.isElement("conserved quantity key") and \ asearch.child_by_name(snow_dist_pk,"conserved quantity key").getValue() == "surface-precipitation_snow": asearch.child_by_name(snow_dist_pk,"conserved quantity key").setValue("snow-precipitation") if snow_dist_pk.isElement("domain name") and \ asearch.child_by_name(snow_dist_pk,"domain name").getValue() == "surface": asearch.child_by_name(snow_dist_pk,"domain name").setValue("snow") try: ssk = asearch.find_path(xml, ["state","field evaluators","snow-conductivity"]) except aerrors.MissingXMLError: pass else: if ssk.isElement("height key"): asearch.child_by_name(ssk, "height key").setValue("snow-precipitation")
def water_energy(xml): try: water = asearch.find_path( xml, ["state", "field evaluators", "water_content"]) except aerrors.MissingXMLError: pass else: ftype = water.getElement("field evaluator type") if ftype.value == "permafrost water content": if water.isElement("include water vapor") and water.getElement( "include water vapor").value: ftype.setValue("three phase water content") else: ftype.setValue("liquid+ice water content") elif ftype.value == "richards water content": if water.isElement("include water vapor") and water.getElement( "include water vapor").value: ftype.setValue("liquid+gas water content") else: ftype.setValue("richards water content") try: energy = asearch.find_path(xml, ["state", "field evaluators", "energy"]) except aerrors.MissingXMLError: pass else: etype = energy.getElement("field evaluator type") if ftype.value == "three phase water content": etype.setValue("three phase energy") elif ftype.value == "liquid+ice water content": etype.setValue("liquid+ice energy") elif ftype.value == "liquid+gas water content": etype.setValue("liquid+gas energy") elif ftype.value == "richards water content": etype.setValue("richards energy")
def checkManning(xml): fe_list = asearch.find_path(xml, ["state", "field evaluators"]) for eval in fe_list: ename = eval.getName() if ename.endswith( 'manning_coefficient') and not ename.startswith('snow'): eval_type = eval.getElement('field evaluator type') if eval_type.getValue() == 'independent variable': func_reg = eval.getElement("function") for reg in func_reg: comp_entries = asearch.findall_name(reg, ['components']) if len(comp_entries) > 1: # previous iterations of this script were broken... for entry in comp_entries[1:]: reg.remove(entry) fixed = False if not fixed: try: comp = reg.getElement('component') except aerrors.MissingXMLError: pass else: reg.pop('component') assert len(asearch.findall_name(reg, 'components')) == 0 reg.append( parameter.ArrayStringParameter( 'components', ['cell', 'boundary_face'])) fixed = True if not fixed: try: comp = reg.getElement('components') except aerrors.MissingXMLError: pass else: reg.pop('components') assert len(asearch.findall_name(reg, 'components')) == 0 reg.append( parameter.ArrayStringParameter( 'components', ['cell', 'boundary_face'])) fixed = True if not fixed: print(reg.__str__().decode('utf-8')) raise aerrors.MissingXMLError( 'Missing "component" or "components"')
def adds_source_units(xml): fevals = asearch.find_path(xml, ["state", "field evaluators"]) try: te = fevals.getElement("total_energy_source") except aerrors.MissingXMLError: pass else: if not te.isElement("mass source units"): te.setParameter("mass source units", "string", "mol m^-2 s^-1") try: tes = fevals.getElement("surface-total_energy_source") except aerrors.MissingXMLError: pass else: if not tes.isElement("mass source units"): tes.setParameter("mass source units", "string", "m s^-1")
def snow_distribution(xml): for snow_dist_pk in asearch.gen_path(xml, ["PKs", "snow distribution"]): if snow_dist_pk.isElement("primary variable key") and \ asearch.child_by_name(snow_dist_pk,"primary variable key").getValue() == "surface-precipitation_snow": asearch.child_by_name( snow_dist_pk, "primary variable key").setValue("snow-precipitation") if snow_dist_pk.isElement("conserved quantity key") and \ asearch.child_by_name(snow_dist_pk,"conserved quantity key").getValue() == "surface-precipitation_snow": asearch.child_by_name( snow_dist_pk, "conserved quantity key").setValue("snow-precipitation") if snow_dist_pk.isElement("domain name") and \ asearch.child_by_name(snow_dist_pk,"domain name").getValue() == "surface": asearch.child_by_name(snow_dist_pk, "domain name").setValue("snow") for ssk in asearch.find_path( xml, ["state", "field evaluators", "snow-conductivity"]): if ssk.isElement("height key"): asearch.child_by_name(ssk, "height key").setValue("snow-precipitation")
def checkManning(xml): fe_list = asearch.find_path(xml, ["state", "field evaluators"]) for eval in fe_list: if eval.getName().endswith('manning_coefficient'): eval_type = eval.getElement('field evaluator type') if eval_type.getValue() == 'independent variable': func_reg = eval.getElement("function") for reg in func_reg: fixed = False if not fixed: try: comp = reg.getElement('component') except aerrors.MissingXMLError: pass else: reg.pop('component') reg.append( parameter.ArrayStringParameter( 'components', ['cell', 'boundary_face'])) fixed = True if not fixed: try: comp = reg.getElement('components') except aerrors.MissingXMLError: pass else: reg.pop('components') reg.append( parameter.ArrayStringParameter( 'components', ['cell', 'boundary_face'])) fixed = True if not fixed: print(reg.__str__().decode('utf-8')) raise aerrors.MissingXMLError( 'Missing "component" or "components"')
def fixMassSource(xml): # find all pks pks = asearch.find_name(xml, "PKs") for pk in pks: pk_type = asearch.find_name(pk, "PK type") if pk_type.getValue() in [ "richards", "overland flow, pressure basis", "overland flow", "overland flow with ice", "snow distribution", "richards steady state", "permafrost flow" ]: # has source? try: has_source = asearch.find_name(pk, "source term") except aerrors.MissingXMLError: continue if has_source.getValue(): # check for the default key try: source_name = asearch.find_name(pk, "source key") except aerrors.MissingXMLError: try: source_name_suffix = asearch.find_name( pk, "source key suffix") except aerrors.MissingXMLError: # if we are using the default, check to see if # the old default is in the list of evaluators default_val = _get_prefixed_name(pk, "mass_source") try: source_eval = asearch.find_path( xml, ["state", "field evaluators", default_val]) except aerrors.MissingXMLError: # likely this is a Arctic run, and the # source name is now changed to the new # default, do nothing pass else: # we are using the default, change it to the new default prefix_name = _get_prefixed_name( pk, "water_source") source_eval.setName(prefix_name) else: if source_name_suffix.getValue() == "mass_source": # if we found source key suffix, and it is mass_source... default_val = _get_prefixed_name(pk, "mass_source") try: source_eval = asearch.find_path( xml, ["state", "field evaluators", default_val]) except aerrors.MissingXMLError: # likely this is an Arctic run, and # the source name is now changed to # the new default. Change the suffix source_name_suffix.setValue("water_source") else: # change both the suffix and the evaluator source_name_suffix.setValue("water_source") prefix_name = _get_prefixed_name( pk, "water_source") source_eval.setName( _get_prefixed_name(pk, "water_source")) else: if source_name.getValue().endswith("mass_source"): # we found a source key, and its suffix is mass source... try: source_eval = asearch.find_path( xml, [ "state", "field evaluators", source_name.getValue() ]) except aerrors.MissingXMLError: # likely Arctic if '-' in source_name.getValue(): source_domain = source_name.getValue().split( '-')[0] source_name.setValue(source_domain + '-water_source') else: source_name.setValue('water_source') else: source_domain = source_name.getValue().split( '-')[0] source_name.setValue(source_domain + '-water_source') source_eval.setName(source_domain + '-water_source') # changes "mass source in meters" to "water source". Note this # can be in transport, not only in flow. for ws_in_meters in asearch.findall_name(xml, "mass source in meters"): ws_in_meters.setName("water source in meters") # changes "mass source units" to "water source units" in total energy sources fe_list = asearch.find_path(xml, ["state", "field evaluators"]) for eval in fe_list: if asearch.find_name( eval, "field evaluator type").getValue() == "advected energy source": try: units = asearch.find_name(eval, "mass source units") except aerrors.MissingXMLError: pass else: units.setName("water source units")
def seb_twocomponent(xml, eval_name): """This changes the old, 'Arctic' SEB model into a test-reproducing, same answer input file.""" # area fractions try: frac_area = asearch.find_path( xml, ["state", "field evaluators", "snow-fractional_areas"]) except aerrors.MissingXMLError: pass else: frac_area.setName("surface-fractional_areas") for name in [ 'surface-fractional_areas', 'surface_column:*-fractional_areas' ]: try: frac_area = asearch.find_path(xml, ["state", "field evaluators", name]) except aerrors.MissingXMLError: pass else: domain = frac_area.getName().split('-')[0] frac_area.setName(domain + "-area_fractions") frac_area_type = asearch.child_by_name(frac_area, "field evaluator type") if frac_area_type.getValue() == "surface balance area fractions": frac_area_type.setValue("area fractions, two components") # water source try: water_source = asearch.find_path( xml, ['state', 'field evaluators', eval_name]) except aerrors.MissingXMLError: pass else: water_source_type = asearch.child_by_name(water_source, "field evaluator type") if water_source_type.getValue() == "surface balance": water_source_type.setValue( "surface energy balance, two components") try: asearch.child_by_name(water_source, "use model from ATS 1.1") except aerrors.MissingXMLError: water_source.append( parameter.BoolParameter("use model from ATS 1.1", True)) # subgrid albedos for name in [ 'surface-subgrid_albedos', 'surface_column:*-subgrid_albedos' ]: try: albedo = asearch.find_path(xml, ['state', 'field evaluators', name]) except aerrors.MissingXMLError: pass else: dname = name.split('-')[0] albedo.setName(dname + '-albedos') albedo_type = asearch.child_by_name(albedo, "field evaluator type") if albedo_type.getValue() == "albedo": albedo_type.setValue("two-component subgrid albedos")
def seb(xml): pk_list = asearch.findall_name(xml, "PKs") assert (len(pk_list) == 1) pk_list = pk_list[0] seb_pk = None flow_sub_pk = None flow_surf_pk = None energy_sub_pk = None energy_surf_pk = None # make sure we can find all of them! for pk in pk_list: if asearch.child_by_name( pk, "PK type").getValue() == "surface balance implicit": if seb_pk is not None: raise RuntimeError("Cannot deal with SEB changes!") seb_pk = pk elif asearch.child_by_name(pk, "PK type").getValue() == "permafrost flow": if flow_sub_pk is not None: raise RuntimeError("Cannot deal with SEB changes!") flow_sub_pk = pk elif asearch.child_by_name( pk, "PK type").getValue() == "overland flow with ice": if flow_surf_pk is not None: raise RuntimeError("Cannot deal with SEB changes!") flow_surf_pk = pk elif asearch.child_by_name( pk, "PK type").getValue() == "three-phase energy": if energy_sub_pk is not None: raise RuntimeError("Cannot deal with SEB changes!") energy_sub_pk = pk elif asearch.child_by_name(pk, "PK type").getValue() == "surface energy": if energy_surf_pk is not None: raise RuntimeError("Cannot deal with SEB changes!") energy_surf_pk = pk if seb_pk is None or flow_sub_pk is None or flow_surf_pk is None or energy_sub_pk is None or energy_surf_pk is None: return # check the source terms for all def set_source_term(pk): if not pk.isElement("source term"): pk.append(parameter.BoolParameter("source term", True)) else: asearch.child_by_name(pk, "source term").set("value", "true") set_source_term(flow_sub_pk) set_source_term(flow_surf_pk) set_source_term(energy_sub_pk) set_source_term(energy_surf_pk) if not flow_sub_pk.isElement("mass source key"): flow_sub_pk.append( parameter.StringParameter("mass source key", "mass_source")) if not flow_surf_pk.isElement("source key"): flow_surf_pk.append( parameter.StringParameter("source key", "surface-mass_source")) if not flow_surf_pk.isElement("mass source in meters"): flow_surf_pk.append( parameter.BoolParameter("mass source in meters", True)) if not energy_sub_pk.isElement("energy source"): energy_sub_pk.append( parameter.StringParameter("energy source", "total_energy_source")) if not energy_surf_pk.isElement("energy source"): energy_surf_pk.append( parameter.StringParameter("energy source", "surface-total_energy_source")) eval_list = asearch.find_path(xml, ["state", "field evaluators"]) try: eval_list.pop("surface-total_energy_source") except aerrors.MissingXMLError: pass try: eval_list.pop("surface-mass_source_enthalpy") except aerrors.MissingXMLError: pass try: eval_list.pop("surface-source_internal_energy") except aerrors.MissingXMLError: pass molar_dens = asearch.child_by_name(eval_list, "surface-source_molar_density") if molar_dens.isElement("temperature key"): asearch.child_by_name(molar_dens, "temperature key").set("value", "surface-temperature") else: molar_dens.append( parameter.StringParameter("temperature key", "surface-temperature"))
def getRegionList(self): return search.find_path(self.xml, [ "amanzi_input", "regions", ], False)