{ "cells": [ { "cell_type": "markdown", "id": "9a574759-032d-43f1-a1f4-cdb53eb9692a", "metadata": {}, "source": [ "# 0e - Estimate the response timescale for every glacier model and experiment (for the shifted simulations)\n", "\n", "- response timescale estimated at mass shrinkage rates of -50%, -80% and -90%. The response timescales is only computed if at least 25% of the mass is lost (otherwise the noise is too large)...\n", "\n", "The following file is created, which is later used in other notebooks for the analysis and visualisations:\n", "`'../data/resp_time_shifted_for_deltaT_rgi_reg_roll_volume_21yravg.csv'`" ] }, { "cell_type": "code", "execution_count": 1, "id": "6d79abd8-8da7-4ee9-88a5-8d69ec1a81b8", "metadata": {}, "outputs": [], "source": [ "\n", "DATE = 'Feb12_2024' \n", "fill_option = 'repeat_last_101yrs'\n", "\n", "import xarray as xr\n", "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "\n", "approach = '_via_5yravg'\n", "\n", "\n", "# the non-shifted stuff is just read in for some tests ... \n", "path_merged_runs_scaled_extend = f'../data/GMIP3_reg_glacier_model_data/glacierMIP3_{DATE}_models_all_rgi_regions_sum_scaled_extended_{fill_option}.nc'\n", "ds_reg_models_extend = xr.open_dataset(path_merged_runs_scaled_extend)\n", "ds_reg_yr_shift= xr.open_dataset(f'../data/GMIP3_reg_glacier_model_data/all_shifted_glacierMIP3_{DATE}_models_all_rgi_regions_sum_scaled_extended_{fill_option}{approach}.nc')\n", "\n", "# only select final submission data\n", "glac_models = ['CISM2', 'GO', 'PyGEM-OGGM_v13', 'GloGEMflow', 'Kraaijenbrink',\n", " 'GLIMB','OGGM_v16', 'GloGEMflow3D']\n", "ds_reg_models_extend = ds_reg_models_extend.sel(model_author = glac_models)\n", "ds_reg_yr_shift = ds_reg_yr_shift.sel(model_author = glac_models)\n", "\n", "pd_avg_exps= pd.read_csv('../data/climate_input_data/temp_ch_ipcc_ar6_isimip3b.csv', index_col=[0])\n", "pd_global_temp_exp_m = pd_avg_exps.set_index(['gcm', 'period_scenario'])" ] }, { "cell_type": "code", "execution_count": 37, "id": "e78d082b-64cc-4e45-8563-a20e58745afb", "metadata": {}, "outputs": [], "source": [ "global_models = ds_reg_models_extend.sel(simulation_year=0).dropna(dim='model_author',how='any').model_author.values" ] }, { "cell_type": "code", "execution_count": 38, "id": "3eea1380-031e-44f9-ae9a-9febcebb2ac5", "metadata": {}, "outputs": [], "source": [ "def resp_time_estimate(model_author='OGGM_v16', perc_change_l=[-50],\n", " rgi_reg='11', min_perc_change=25, roll_volume=21, shift_years=False):\n", " # computes the response timescale estimates for all 80 experiments of a given model_author and rgi_reg \n", " # perc_change : -50 (gives estimates of how fast 50% of total volume change occurs), also -80 is used in the manuscript\n", " # min_perc_change: minimum shrinkage/growing to estimate a \"response time\" (%)\n", " # HERE, the first occurrence of -50% change over the roll_volume avg. is used, \n", " # alternatively we could use the last occurrence, but this would \"mean\" something different of course ... \n", " # we also select the equilibrium volume by averaging over the last 100 years,\n", " # this is necessary due to the large interdecadal variability of some models\n", " # MAYBE could even select there 200 or 300 years (but then we would also need to check how the data is \"extended\"...\n", " if shift_years:\n", " # we shift by maximum by +50 years, so like that there should always be values inside \n", " _ds_reg_models_extend = ds_reg_yr_shift.sel(year_after_2020=slice(0,4950))\n", " else:\n", " _ds_reg_models_extend = ds_reg_models_extend\n", " if rgi_reg == 'All':\n", " if model_author in global_models:\n", " ds_reg_models_vol_all = _ds_reg_models_extend.volume_m3.sum(dim='rgi_reg')\n", " else:\n", " raise Exception(\"not a global model!!!\")\n", " \n", " else:\n", " ds_reg_models_vol_all = _ds_reg_models_extend.volume_m3.sel(rgi_reg=rgi_reg) # need to do the interpolation first !\n", "\n", " ds_reg_models_vol_all = ds_reg_models_vol_all.stack(experiments=['gcm','period_scenario'])\n", " # merge \"gcm\"s and \"period_scenario\" into one coordinate callled \"experiments\"\n", " ds_reg_models_vol_all = ds_reg_models_vol_all.assign_coords(temp_ch_ipcc = ('experiments',\n", " pd_global_temp_exp_m.loc[ds_reg_models_vol_all.experiments, \n", " 'temp_ch_ipcc']))\n", " ds_reg_models_sel_vol_all = ds_reg_models_vol_all.sel(model_author=model_author)\n", " # steady state is the average of the last 100 years!!!\n", " if shift_years:\n", " v_eq = ds_reg_models_sel_vol_all.sel(year_after_2020=slice(4901-50,5000-50)).mean(dim='year_after_2020')\n", " v0 = ds_reg_models_sel_vol_all.sel(year_after_2020=0) \n", " else:\n", " v_eq = ds_reg_models_sel_vol_all.sel(simulation_year=slice(4901,5000)).mean(dim='simulation_year')\n", " v0 = ds_reg_models_sel_vol_all.isel(simulation_year=0)\n", " \n", " pd_category_resp_time = pd.DataFrame(index=ds_reg_models_vol_all.experiments)\n", " if rgi_reg == 'All':\n", " pd_category_resp_time['rgi_reg'] = f'All'\n", " else:\n", " pd_category_resp_time['rgi_reg'] = f'RGI{rgi_reg}'\n", " pd_category_resp_time['model_author'] = model_author\n", " pd_category_resp_time['min_perc_change'] = min_perc_change\n", "\n", " pd_category_resp_time.loc[ds_reg_models_vol_all.experiments, 'temp_ch_ipcc'] = ds_reg_models_vol_all.temp_ch_ipcc.values\n", " # did it grow, shrink or stay the same??? ... this information is later not anymore used\n", " pd_category_resp_time['category'] = r'similar to V$_{0}$'\n", " grow_exps = v_eq.where(v_eq/v0 >=1+min_perc_change/100, drop=True).experiments.values\n", " pd_category_resp_time.loc[grow_exps, 'category'] = 'grow'\n", " shrink_exps = v_eq.where(v_eq/v0 <=1-min_perc_change/100, drop=True).experiments.values\n", " pd_category_resp_time.loc[shrink_exps, 'category'] = 'shrink'\n", " pd_category_resp_time['shift_years'] = shift_years\n", " for perc_change in perc_change_l:\n", " # response time computation\n", " # V(resp_t) = -perc/100 * (V_eq-v0)+v0)\n", " # we need the absolute because we only want to have either shrinking (negative perc) \n", " # or growing (positive perc) experiments\n", " v_resp_t = v0 + (perc_change/100)*np.abs(v0-v_eq)\n", " if shift_years:\n", " v_roll = ds_reg_models_sel_vol_all.rolling(year_after_2020=roll_volume, center=True).mean()\n", " # we take the last year where the anti-condition holds true (so it is basically the first year where the condition holds true)\n", " resp_t = v_roll.where(v_roll<=v_resp_t).idxmax(dim='year_after_2020')\n", " #print(v_roll, resp_t)\n", " else:\n", " v_roll = ds_reg_models_sel_vol_all.rolling(simulation_year=roll_volume, center=True).mean()\n", " # we take the last year where the anti-condition holds true (so it is basically the first year where the condition holds true)\n", " resp_t = v_roll.where(v_roll<=v_resp_t).idxmax(dim='simulation_year')\n", " if perc_change<0:\n", " # if we look at how much it shrinks it should at least shrink by min_perc_change to estimate a \"response time\"\n", " resp_t = resp_t.where(v_eq/v0 <=1-min_perc_change/100, np.NaN)\n", " else:\n", " # if we look at how much it grows it should at least grow by min_perc_change to estimate a \"response time\"\n", " resp_t = resp_t.where(v_eq/v0 >=1+min_perc_change/100, np.NaN)\n", " if perc_change>0:\n", " perc_change_i = f'+{perc_change}'\n", " else:\n", " perc_change_i = perc_change\n", " pd_category_resp_time.loc[resp_t.experiments,f'resp_time_{perc_change_i}%'] = resp_t.values\n", " \n", " return pd_category_resp_time" ] }, { "cell_type": "markdown", "id": "88f5c4e3-4b2b-4df7-a787-5666419f460a", "metadata": {}, "source": [ "just some random response timescale test estimates ... with and without shifting the experiments to start in year 2020..." ] }, { "cell_type": "code", "execution_count": 39, "id": "aeae7971-5833-4477-9b29-10cc0115d65f", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
| \n", " | rgi_reg | \n", "model_author | \n", "min_perc_change | \n", "temp_ch_ipcc | \n", "category | \n", "shift_years | \n", "resp_time_-50% | \n", "
|---|---|---|---|---|---|---|---|
| (gfdl-esm4, 1851-1870_hist) | \n", "All | \n", "GLIMB | \n", "25 | \n", "0.231409 | \n", "similar to V$_{0}$ | \n", "False | \n", "NaN | \n", "
| (gfdl-esm4, 1901-1920_hist) | \n", "All | \n", "GLIMB | \n", "25 | \n", "0.478289 | \n", "shrink | \n", "False | \n", "346.0 | \n", "
| (gfdl-esm4, 1951-1970_hist) | \n", "All | \n", "GLIMB | \n", "25 | \n", "0.392281 | \n", "shrink | \n", "False | \n", "370.0 | \n", "
| (gfdl-esm4, 1995-2014_hist) | \n", "All | \n", "GLIMB | \n", "25 | \n", "0.901467 | \n", "shrink | \n", "False | \n", "284.0 | \n", "
| (gfdl-esm4, 2021-2040_ssp126) | \n", "All | \n", "GLIMB | \n", "25 | \n", "1.493792 | \n", "shrink | \n", "False | \n", "237.0 | \n", "
| ... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
| (ukesm1-0-ll, 2061-2080_ssp370) | \n", "All | \n", "GLIMB | \n", "25 | \n", "4.439977 | \n", "shrink | \n", "False | \n", "72.0 | \n", "
| (ukesm1-0-ll, 2061-2080_ssp585) | \n", "All | \n", "GLIMB | \n", "25 | \n", "5.230543 | \n", "shrink | \n", "False | \n", "59.0 | \n", "
| (ukesm1-0-ll, 2081-2100_ssp126) | \n", "All | \n", "GLIMB | \n", "25 | \n", "3.038482 | \n", "shrink | \n", "False | \n", "99.0 | \n", "
| (ukesm1-0-ll, 2081-2100_ssp370) | \n", "All | \n", "GLIMB | \n", "25 | \n", "5.840495 | \n", "shrink | \n", "False | \n", "51.0 | \n", "
| (ukesm1-0-ll, 2081-2100_ssp585) | \n", "All | \n", "GLIMB | \n", "25 | \n", "6.884361 | \n", "shrink | \n", "False | \n", "40.0 | \n", "
80 rows × 7 columns
\n", "| \n", " | rgi_reg | \n", "model_author | \n", "volume_m3 | \n", "
|---|---|---|---|
| 0 | \n", "01 | \n", "CISM2 | \n", "0 | \n", "
| 1 | \n", "01 | \n", "GLIMB | \n", "80 | \n", "
| 2 | \n", "01 | \n", "GO | \n", "0 | \n", "
| 3 | \n", "01 | \n", "GloGEMflow | \n", "80 | \n", "
| 4 | \n", "01 | \n", "GloGEMflow3D | \n", "0 | \n", "
| ... | \n", "... | \n", "... | \n", "... | \n", "
| 147 | \n", "19 | \n", "GloGEMflow | \n", "80 | \n", "
| 148 | \n", "19 | \n", "GloGEMflow3D | \n", "0 | \n", "
| 149 | \n", "19 | \n", "Kraaijenbrink | \n", "0 | \n", "
| 150 | \n", "19 | \n", "OGGM_v16 | \n", "80 | \n", "
| 151 | \n", "19 | \n", "PyGEM-OGGM_v13 | \n", "80 | \n", "
152 rows × 3 columns
\n", "| \n", " | rgi_reg | \n", "model_author | \n", "temp_ch_ipcc | \n", "gcm_period_scenario | \n", "min_perc_change | \n", "resp_time_-50% | \n", "resp_time_-80% | \n", "resp_time_-90% | \n", "diff_resp_time_-50% | \n", "diff_resp_time_-80% | \n", "diff_resp_time_-90% | \n", "
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | \n", "All | \n", "GLIMB | \n", "0.302892 | \n", "ipsl-cm6a-lr_1951-1970_hist | \n", "25 | \n", "420.0 | \n", "1138.0 | \n", "1785.0 | \n", "88.0 | \n", "208.0 | \n", "282.5 | \n", "
| 1 | \n", "All | \n", "GLIMB | \n", "0.478289 | \n", "gfdl-esm4_1901-1920_hist | \n", "25 | \n", "382.0 | \n", "1152.0 | \n", "1877.0 | \n", "87.0 | \n", "260.5 | \n", "397.5 | \n", "
| 2 | \n", "All | \n", "GLIMB | \n", "0.901467 | \n", "gfdl-esm4_1995-2014_hist | \n", "25 | \n", "312.0 | \n", "1001.0 | \n", "1660.0 | \n", "122.0 | \n", "440.0 | \n", "720.0 | \n", "
| 3 | \n", "All | \n", "GLIMB | \n", "0.904940 | \n", "mpi-esm1-2-hr_1995-2014_hist | \n", "25 | \n", "329.0 | \n", "1032.0 | \n", "1763.0 | \n", "148.0 | \n", "511.0 | \n", "888.0 | \n", "
| 4 | \n", "All | \n", "GLIMB | \n", "0.913313 | \n", "ipsl-cm6a-lr_1995-2014_hist | \n", "25 | \n", "307.0 | \n", "966.0 | \n", "1597.0 | \n", "135.0 | \n", "483.0 | \n", "781.0 | \n", "
| ... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
| 6010 | \n", "RGI19 | \n", "PyGEM-OGGM_v13 | \n", "4.677751 | \n", "ipsl-cm6a-lr_2081-2100_ssp370 | \n", "25 | \n", "123.0 | \n", "275.0 | \n", "374.0 | \n", "22.0 | \n", "25.0 | \n", "-38.0 | \n", "
| 6011 | \n", "RGI19 | \n", "PyGEM-OGGM_v13 | \n", "5.230543 | \n", "ukesm1-0-ll_2061-2080_ssp585 | \n", "25 | \n", "116.0 | \n", "267.0 | \n", "377.0 | \n", "30.0 | \n", "40.5 | \n", "10.0 | \n", "
| 6012 | \n", "RGI19 | \n", "PyGEM-OGGM_v13 | \n", "5.840495 | \n", "ukesm1-0-ll_2081-2100_ssp370 | \n", "25 | \n", "69.0 | \n", "158.0 | \n", "223.0 | \n", "17.5 | \n", "30.0 | \n", "31.0 | \n", "
| 6013 | \n", "RGI19 | \n", "PyGEM-OGGM_v13 | \n", "5.849305 | \n", "ipsl-cm6a-lr_2081-2100_ssp585 | \n", "25 | \n", "93.0 | \n", "204.0 | \n", "277.0 | \n", "18.0 | \n", "34.5 | \n", "37.5 | \n", "
| 6014 | \n", "RGI19 | \n", "PyGEM-OGGM_v13 | \n", "6.884361 | \n", "ukesm1-0-ll_2081-2100_ssp585 | \n", "25 | \n", "58.0 | \n", "132.0 | \n", "184.0 | \n", "15.5 | \n", "31.5 | \n", "40.0 | \n", "
6015 rows × 11 columns
\n", "