From 936e5a0145b8d9454a69e12663def2b9bf57a59b Mon Sep 17 00:00:00 2001 From: Harrison Nicholls Date: Thu, 25 Jul 2024 14:41:59 +0100 Subject: [PATCH] Tidied things up. Updated plots. Updated cfgs and docs with new parameter. --- docs/source/usage.rst | 8 ++++- input/default.cfg | 1 + input/dummy.cfg | 1 + input/janus_mixed.cfg | 1 + input/jgr_grid.cfg | 1 + input/rce_mixed.cfg | 2 ++ input/rce_steam.cfg | 1 + proteus.py | 13 +++++--- utils/coupler.py | 76 ++++++++++++++++++++++++------------------- utils/escape.py | 23 ++++++------- 10 files changed, 76 insertions(+), 51 deletions(-) diff --git a/docs/source/usage.rst b/docs/source/usage.rst index c174e8f4..76fc1292 100644 --- a/docs/source/usage.rst +++ b/docs/source/usage.rst @@ -267,7 +267,13 @@ configuration, but they must all be passed via the config file. - Stop the simulation when the atmosphere mass drops below this fraction of its initial mass. - False - Float - - Values between zero and unity. + - Values between zero and unity (exclusive). + + * - ``escape_dummy_rate`` + - Bulk escape rate for dummy escape model [kg s-1] + - False + - Float + - Any reasonable positive value. * - ``prevent_warming`` - Flag to ensure that the net upward energy flux is always positive, which prevents the star from causing net heating inside the planet. diff --git a/input/default.cfg b/input/default.cfg index b65ccb68..90004be8 100644 --- a/input/default.cfg +++ b/input/default.cfg @@ -77,6 +77,7 @@ F_crit = 0.2 # Critical flux, below which the model w # Atmospheric escape escape_model = 0 # Escape model to be used, 0: None | 1: ZEPHYRUS | 2: Dummy escape_stop = 3e-4 # Terminate when atm mass drops below this fraction of its initial mass +escape_dummy_rate = 0.0 # Bulk escape rate for dummy escape model [kg s-1] # Method for solving for T(p) profile atmosphere_model = 0 # Atmosphere model to be used, 0: JANUS | 1: AGNI diff --git a/input/dummy.cfg b/input/dummy.cfg index 6c7542f7..d7905f95 100644 --- a/input/dummy.cfg +++ b/input/dummy.cfg @@ -77,6 +77,7 @@ F_crit = 0.2 # Model will terminate when |F_atm| < F_ # Atmospheric escape escape_model = 2 # Escape model to be used, 0: None | 1: ZEPHYRUS | 2: Dummy escape_stop = 3e-4 # Terminate when atm mass drops below this fraction of its initial mass +escape_dummy_rate = 2e7 # Bulk escape rate for dummy escape model [kg s-1] # Method for solving for T(p) profile atmosphere_model = 2 # Atmosphere model to be used, 0: JANUS | 1: AGNI | 2: Dummy diff --git a/input/janus_mixed.cfg b/input/janus_mixed.cfg index dfc0be37..d0b38d53 100644 --- a/input/janus_mixed.cfg +++ b/input/janus_mixed.cfg @@ -77,6 +77,7 @@ F_crit = 0.2 # Model will terminate when |F_atm| < F_ # Atmospheric escape escape_model = 0 # Escape model to be used, 0: None | 1: ZEPHYRUS | 2: Dummy escape_stop = 3e-4 # Terminate when atm mass drops below this fraction of its initial mass +escape_dummy_rate = 0.0 # Bulk escape rate for dummy escape model [kg s-1] # Method for solving for T(p) profile atmosphere_model = 0 # Atmosphere model to be used, 0: JANUS | 1: AGNI diff --git a/input/jgr_grid.cfg b/input/jgr_grid.cfg index e7e383d1..f7344166 100644 --- a/input/jgr_grid.cfg +++ b/input/jgr_grid.cfg @@ -77,6 +77,7 @@ F_crit = 0.2 # Model will terminate when |F_atm| < F_ # Atmospheric escape escape_model = 0 # Escape model to be used, 0: None | 1: ZEPHYRUS | 2: Dummy escape_stop = 3e-4 # Terminate when atm mass drops below this fraction of its initial mass +escape_dummy_rate = 0.0 # Bulk escape rate for dummy escape model [kg s-1] # Method for solving for T(p) profile atmosphere_model = 0 # Atmosphere model to be used, 0: JANUS | 1: AGNI diff --git a/input/rce_mixed.cfg b/input/rce_mixed.cfg index 139260a4..6e59de44 100644 --- a/input/rce_mixed.cfg +++ b/input/rce_mixed.cfg @@ -77,6 +77,8 @@ F_crit = 0.2 # Model will terminate when |F_atm| < F_ # Atmospheric escape escape_model = 0 # Escape model to be used, 0: None | 1: ZEPHYRUS | 2: Dummy escape_stop = 3e-4 # Terminate when atm mass drops below this fraction of its initial mass +escape_dummy_rate = 0.0 # Bulk escape rate for dummy escape model [kg s-1] + # Method for solving for T(p) profile atmosphere_model = 1 # Atmosphere model to be used, 0: JANUS | 1: AGNI diff --git a/input/rce_steam.cfg b/input/rce_steam.cfg index 8492cfe9..dc7f7016 100644 --- a/input/rce_steam.cfg +++ b/input/rce_steam.cfg @@ -77,6 +77,7 @@ F_crit = 0.2 # Model will terminate when |F_atm| < F_ # Atmospheric escape escape_model = 0 # Escape model to be used, 0: None | 1: ZEPHYRUS | 2: Dummy escape_stop = 3e-4 # Terminate when atm mass drops below this fraction of its initial mass +escape_dummy_rate = 0.0 # Bulk escape rate for dummy escape model [kg s-1] # Method for solving for T(p) profile atmosphere_model = 1 # Atmosphere model to be used, 0: JANUS | 1: AGNI diff --git a/proteus.py b/proteus.py index e16833b4..2f3d767e 100755 --- a/proteus.py +++ b/proteus.py @@ -410,7 +410,7 @@ def main(): esc_result = RunZEPHYRUS() elif COUPLER_options["escape_model"] == 2: - esc_result = RunDummyEsc(hf_row, dt) + esc_result = RunDummyEsc(hf_row, dt, COUPLER_options["escape_dummy_rate"]) # store total escape rate hf_row["esc_rate_total"] = esc_result["rate_bulk"] @@ -419,10 +419,15 @@ def main(): # update elemental mass targets for e in element_list: if e=='O': continue - solvevol_target[e] += esc_result[e+"_dm"] - esc_m = solvevol_target[e] - esc_dm = esc_result[e+"_dm"] + # store change, for statistics + esc_m = esc_result[e+"_kg_total"] + esc_dm = esc_m - solvevol_target[e] + + # update total elemental inventory + solvevol_target[e] = esc_m + + # print info to user log.debug(" escape %s: m=%.2e kg, dm=%.2e (%.3f%%)"% (e, esc_m, esc_dm, 100*esc_dm/esc_m)) diff --git a/utils/coupler.py b/utils/coupler.py index 7fcedd2c..6fdb9db7 100644 --- a/utils/coupler.py +++ b/utils/coupler.py @@ -8,16 +8,17 @@ log = logging.getLogger("PROTEUS") -import plot.cpl_atmosphere as cpl_atmosphere -import plot.cpl_global as cpl_global -import plot.cpl_stacked as cpl_stacked -import plot.cpl_interior as cpl_interior -import plot.cpl_sflux as cpl_sflux -import plot.cpl_sflux_cross as cpl_sflux_cross -import plot.cpl_fluxes_global as cpl_fluxes_global -import plot.cpl_fluxes_atmosphere as cpl_fluxes_atmosphere -import plot.cpl_interior_cmesh as cpl_interior_cmesh -import plot.cpl_observables as cpl_observables +from plot.cpl_atmosphere import plot_atmosphere +from plot.cpl_global import plot_global +from plot.cpl_stacked import plot_stacked +from plot.cpl_interior import plot_interior +from plot.cpl_sflux import plot_sflux +from plot.cpl_sflux_cross import plot_sflux_cross +from plot.cpl_fluxes_global import plot_fluxes_global +from plot.cpl_fluxes_atmosphere import plot_fluxes_atmosphere +from plot.cpl_interior_cmesh import plot_interior_cmesh +from plot.cpl_observables import plot_observables +from plot.cpl_elements import plot_elements def GitRevision(dir:str) -> str: ''' @@ -117,8 +118,8 @@ def GetHelpfileKeys(): "z_obs", "transit_depth", "contrast_ratio", # observed from infinity # Escape - "esc_rate_total", - + "esc_rate_total", + # Atmospheric composition "M_atm", "P_surf", "atm_kg_per_mol", # more keys added below ] @@ -272,11 +273,14 @@ def ReadInitFile(init_file_passed:str, verbose=False): if not line.startswith("time_"): # Some parameters are int - if key in [ "solid_stop", "steady_stop", "iter_max", "emit_stop", "escape_model", - "plot_iterfreq", "stellar_heating", "mixing_length", "shallow_ocean_layer", - "atmosphere_chemistry", "solvevol_use_params", "insert_rscatter", "water_cloud", - "tropopause", "F_atm_bc", "atmosphere_solve_energy", "atmosphere_surf_state", - "dt_dynamic", "prevent_warming", "atmosphere_model", "atmosphere_nlev"]: + if key in [ "solid_stop", "steady_stop", "iter_max", "emit_stop", + "escape_model", "atmosphere_surf_state", "water_cloud", + "plot_iterfreq", "stellar_heating", "mixing_length", + "atmosphere_chemistry", "solvevol_use_params", + "tropopause", "F_atm_bc", "atmosphere_solve_energy", + "dt_dynamic", "prevent_warming", "atmosphere_model", + "atmosphere_nlev", "insert_rscatter", + "shallow_ocean_layer", "SEPARATION"]: val = int(val) # Some are str @@ -365,15 +369,22 @@ def UpdatePlots( output_dir, COUPLER_options, end=False, num_snapshots=7): """ + + # Check model configuration + dummy_atm = bool(COUPLER_options["atmosphere_model"] == 2) + escape = bool(COUPLER_options["escape_model"] > 0) + + # Get all JSON files output_times = get_all_output_times( output_dir ) # Global properties for all timesteps - if len(output_times) > 1: - cpl_global.plot_global(output_dir, COUPLER_options) + if len(output_times) > 2: + plot_global(output_dir, COUPLER_options) - # Check if we are using the dummy atmosphere - dummy_atm = (COUPLER_options["atmosphere_model"] == 2) + # Elemental mass inventory + if escape: + plot_elements(output_dir, COUPLER_options["plot_format"]) # Filter to JSON files with corresponding NetCDF files if not dummy_atm: @@ -402,25 +413,24 @@ def UpdatePlots( output_dir, COUPLER_options, end=False, num_snapshots=7): plot_times = sorted(set(plot_times)) # Remove any duplicates + resort log.debug("Snapshots to plot:" + str(plot_times)) - # Specific timesteps for paper plots - cpl_interior.plot_interior(output_dir, plot_times, COUPLER_options["plot_format"]) + # Temperature profiles + plot_interior(output_dir, plot_times, COUPLER_options["plot_format"]) if not dummy_atm: - cpl_atmosphere.plot_atmosphere(output_dir, plot_times, COUPLER_options["plot_format"]) - cpl_stacked.plot_stacked(output_dir, plot_times, COUPLER_options["plot_format"]) + plot_atmosphere(output_dir, plot_times, COUPLER_options["plot_format"]) + plot_stacked(output_dir, plot_times, COUPLER_options["plot_format"]) if COUPLER_options["atmosphere_model"] != 1: # don't make this plot for AGNI, since it will do it itself - cpl_fluxes_atmosphere.plot_fluxes_atmosphere(output_dir, COUPLER_options["plot_format"]) - + plot_fluxes_atmosphere(output_dir, COUPLER_options["plot_format"]) # Only at the end of the simulation if end: - cpl_global.plot_global(output_dir, COUPLER_options, logt=False) - cpl_interior_cmesh.plot_interior_cmesh(output_dir, plot_format=COUPLER_options["plot_format"]) - cpl_sflux.plot_sflux(output_dir, plot_format=COUPLER_options["plot_format"]) - cpl_sflux_cross.plot_sflux_cross(output_dir, plot_format=COUPLER_options["plot_format"]) - cpl_fluxes_global.plot_fluxes_global(output_dir, COUPLER_options) - cpl_observables.plot_observables(output_dir, plot_format=COUPLER_options["plot_format"]) + plot_global(output_dir, COUPLER_options, logt=False) + plot_interior_cmesh(output_dir, plot_format=COUPLER_options["plot_format"]) + plot_sflux(output_dir, plot_format=COUPLER_options["plot_format"]) + plot_sflux_cross(output_dir, plot_format=COUPLER_options["plot_format"]) + plot_fluxes_global(output_dir, COUPLER_options) + plot_observables(output_dir, plot_format=COUPLER_options["plot_format"]) # Close all figures plt.close() diff --git a/utils/escape.py b/utils/escape.py index 8adc1f04..04d0a501 100644 --- a/utils/escape.py +++ b/utils/escape.py @@ -7,7 +7,7 @@ log = logging.getLogger("PROTEUS") -def RunDummyEsc(hf_row:dict, dt:float): +def RunDummyEsc(hf_row:dict, dt:float, phi_bulk:float): """Run dummy escape model. Parameters @@ -16,43 +16,40 @@ def RunDummyEsc(hf_row:dict, dt:float): Dictionary of helpfile variables, at this iteration only dt : float Time interval over which escape is occuring [yr] + phi_bulk : float + Bulk escape rate [kg s-1] Returns ---------- esc_result : dict - Dictionary of elemental mass deltas [kg] + Dictionary of updated total elemental mass inventories [kg] """ log.info("Running dummy escape...") - # Hardcoded dummy value of bulk volatile escape rate [kg/s] - phi = 2e7 - # store value out = {} - out["rate_bulk"] = phi + out["rate_bulk"] = phi_bulk - # calculate total mass of volatiles + # calculate total mass of volatiles (except oxygen, which is set by fO2) M_vols = 0.0 for e in element_list: if e=='O': continue M_vols += hf_row[e+"_kg_total"] + # for each elem, calculate new total inventory while # maintaining a constant mass mixing ratio for e in element_list: if e=='O': continue - # current elemental mass ratio in atmosphere + # current elemental mass ratio in total emr = hf_row[e+"_kg_total"]/M_vols log.debug(" %s mass ratio = %.2e "%(e,emr)) - # new atmosphere mass of element e, keeping a constant mixing ratio of that element - e_atm = emr * (M_vols - phi * dt * secs_per_year) - - # calculate change in total mass of element e - out[e+"_dm"] = e_atm - hf_row[e+"_kg_total"] + # new total mass of element e, keeping a constant mixing ratio of that element + out[e+"_kg_total"] = emr * (M_vols - phi_bulk * dt * secs_per_year) return out