def test_timestepping(self): steps = ['ambitious', 'default', 'conservative', 'ultra-conservative'][::-1] lens = [] surface_h = [] volume = [] yrs = np.arange(1, 400, 2) for step in steps: fls = dummy_constant_bed() mb = LinearMassBalance(2600.) model = FluxBasedModel(fls, mb_model=mb, glen_a=self.glen_a, time_stepping=step) length = yrs * 0. vol = yrs * 0. for i, y in enumerate(yrs): model.run_until(y) length[i] = fls[-1].length_m vol[i] = fls[-1].volume_km3 lens.append(length) volume.append(vol) surface_h.append(fls[-1].surface_h.copy()) np.testing.assert_allclose(volume[0][-1], volume[1][-1], atol=1e-2) np.testing.assert_allclose(volume[0][-1], volume[2][-1], atol=1e-2) np.testing.assert_allclose(volume[0][-1], volume[3][-1], atol=1e-2)
def get_first_guess_surface_h(data_logger): """TODO: Function to conduct spinup for first guess surface_h""" fl = data_logger.flowline_init if 'surface_h' in list(data_logger.spinup_options.keys()): mb_options = data_logger.spinup_options['surface_h']['mb_model'] if mb_options['type'] == 'constant': yr_start_run = mb_options['years'][0] yr_end_run = mb_options['years'][1] halfsize = (yr_end_run - yr_start_run) / 2 mb_spinup = MultipleFlowlineMassBalance( data_logger.gdir, fls=[fl], mb_model_class=ConstantMassBalance, filename='climate_historical', input_filesuffix='', y0=yr_start_run + halfsize, halfsize=halfsize) mb_spinup.temp_bias = mb_options['t_bias'] model = FluxBasedModel(copy.deepcopy([fl]), mb_spinup, y0=yr_start_run) model.run_until(yr_end_run) return model.fls[0].surface_h else: raise NotImplementedError( f'mb type {mb_options["type"]} not implemented!') else: raise NotImplementedError( 'The provided spinup option is not implemented!')
def test_limiter(self, default_calving): _, ds1, df_diag1 = default_calving model = FluxBasedModel(bu_tidewater_bed(), mb_model=ScalarMassBalance(), is_tidewater=True, calving_use_limiter=False, flux_gate=0.06, do_kcalving=True, calving_k=0.2) _, ds2 = model.run_until_and_store(3000) df_diag2 = model.get_diagnostics() assert_allclose(model.volume_m3 + model.calving_m3_since_y0, model.flux_gate_m3_since_y0) assert_allclose(ds2.calving_m3[-1], model.calving_m3_since_y0) # Not exact same of course assert_allclose(ds1.volume_m3[-1], ds2.volume_m3[-1], rtol=0.06) assert_allclose(ds1.calving_m3[-1], ds2.calving_m3[-1], rtol=0.15) if do_plot: f, ax = plt.subplots(1, 1, figsize=(12, 5)) df_diag1[['surface_h']].plot(ax=ax, color=['C3']) df_diag2[['surface_h', 'bed_h']].plot(ax=ax, color=['C1', 'k']) plt.hlines(0, 0, 60000, color='C0', linestyles=':') plt.ylim(-350, 800) plt.ylabel('Altitude [m]') plt.show()
def test_boundaries(self): fls = dummy_constant_bed() mb = LinearMassBalance(2000.) model = FluxBasedModel(fls, mb_model=mb, y0=0., glen_a=self.glen_a, fs=self.fs) with pytest.raises(RuntimeError) as excinfo: model.run_until(300) assert 'exceeds domain boundaries' in str(excinfo.value)
def test_run_until_and_store(self): fls = dummy_constant_bed() mb = LinearMassBalance(2600.) model = FluxBasedModel(fls, mb_model=mb) ds_f, ds_d = model.run_until_and_store(150) assert ds_d['length_m'][-1] > 1e3 df = model.get_diagnostics() assert (df['ice_velocity'].max() * cfg.SEC_IN_YEAR) > 10
def test_flux_gate_with_trib(self): mb = ScalarMassBalance() model = FluxBasedModel(dummy_width_bed_tributary(), mb_model=mb, flux_gate_thickness=150, flux_gate_build_up=50) model.run_until(1000) assert_allclose(model.volume_m3, model.flux_gate_m3_since_y0) if do_plot: # pragma: no cover plt.plot(model.fls[-1].bed_h, 'k') plt.plot(model.fls[-1].surface_h, 'b') plt.show()
def default_calving(): cfg.initialize() model = FluxBasedModel(bu_tidewater_bed(), mb_model=ScalarMassBalance(), is_tidewater=True, calving_use_limiter=True, flux_gate=0.06, do_kcalving=True, calving_k=0.2) _, ds = model.run_until_and_store(3000) df_diag = model.get_diagnostics() assert_allclose(model.volume_m3 + model.calving_m3_since_y0, model.flux_gate_m3_since_y0) assert_allclose(ds.calving_m3[-1], model.calving_m3_since_y0) return model, ds, df_diag
def run_model(param, gdir, y_t, random_climate2, t0, te): ''' :param param: temp bias, is changed by optimization :param gdir: oggm.GlacierDirectory :param y_t: oggm.Flowline for the observed state (2000) :param random_climate2: oggm.massbalance.RandomMassBalance :return: 2 oggm.flowline.FluxBasedModels (glacier candidate and predicted glacier model) ''' # run estimated glacier with random climate 2 until equilibrium # (glacier candidate) # estimated flowline = observed flowline estimated_fls = deepcopy(y_t) climate = deepcopy(random_climate2) # change temp_bias climate.temp_bias = param random_model = FluxBasedModel(estimated_fls, mb_model=climate, y0=t0) random_model.run_until_equilibrium() # run glacier candidate with past climate until 2000 candidate_fls = deepcopy(y_t) for i in range(len(y_t)): candidate_fls[i].surface_h = random_model.fls[i].surface_h past_climate = PastMassBalance(gdir) past_model = FluxBasedModel(candidate_fls, mb_model=past_climate, glen_a=cfg.A, y0=t0) past_model.run_until(te) return [random_model, past_model]
def run_model(param, gdir, start_fls, t, i): fls = gdir.read_pickle('model_flowlines') fls1 = copy.deepcopy(fls) fls1[-1].surface_h = copy.deepcopy(y_start.fls[-1].surface_h) climate = copy.deepcopy(past_climate) #climate= RandomMassBalance(gdir) climate.temp_bias = param model = FluxBasedModel(fls1, mb_model=climate, glen_a=i * cfg.A, y0=1850) model.run_until(1850 + t) fls2 = copy.deepcopy(fls) fls2[-1].surface_h = model.fls[-1].surface_h real_model = FluxBasedModel(fls2, mb_model=past_climate, glen_a=cfg.A, y0=1850) real_model.run_until(2000) dif = real_model.fls[-1].surface_h - y_1900.fls[-1].surface_h s = np.sum(np.abs(dif)) #ax1.plot(x, model.fls[-1].surface_h, label='optimum') #ax2.plot(x, real_model.fls[-1].surface_h) #ax3.plot(x, dif) return [model, real_model]
def minimize_dl(tbias, mb, fls, dl, len2003, gdir, optimization, runsuffix=''): # Mass balance mb.temp_bias = tbias model = FluxBasedModel(fls, mb_model=mb) try: model.run_until_equilibrium(ystep=10, max_ite=200) except FloatingPointError: if optimization is True: log.info('(%s) tbias of %.2f gave length: %.2f' % (gdir.rgi_id, tbias, model.length_m)) return len2003**2 else: raise RuntimeError('This should never happen...') except RuntimeError as err: if (optimization is True) and\ ('Glacier exceeds domain boundaries' in err.args[0]): log.info('(%s) tbias of %.2f exceeds domain boundaries' % (gdir.rgi_id, tbias)) return len2003**2 elif (optimization is True) and \ ('Did not find equilibrium' in err.args[0]): log.info('(%s) tbias of %.2f did exceed max iterations' % (gdir.rgi_id, tbias)) return len2003**2 elif 'CFL error' in err.args[0]: log.info('(%s) tbias of %.2f leads to CFL error' % (gdir.rgi_id, tbias)) print(err) return len2003**2 else: print(err) raise RuntimeError('This should never happen 2...') if optimization is True: if model.length_m < fls[-1].dx_meter: log.info('(%s) tbias of %.2f gave length: %.2f' % (gdir.rgi_id, tbias, model.length_m)) return len2003**2 dl_spinup = model.length_m - len2003 delta = (dl - dl_spinup)**2 print('%s: tbias: %.2f delta: %.4f' % (gdir.rgi_id, tbias, delta)) return delta else: filesuffix = '_spinup' + runsuffix run_path = gdir.get_filepath('model_run', filesuffix=filesuffix, delete=True) diag_path = gdir.get_filepath('model_diagnostics', filesuffix=filesuffix, delete=True) model2 = FluxBasedModel(fls, mb_model=mb) model2.run_until_and_store(model.yr, run_path=run_path, diag_path=diag_path)
def init_model(init_flowline, mb_model, years, glen_a=None, fs=None): """This function initializes a new model, therefore it uses FluxBasedModel. The outline of the glacier is calculated for a chosen amount of years. Parameters ---------- init_flowline : oggm.core.flowline.RectangularBedFlowline the glacier flowline mb_model : oggm.core.massbalance.LinearMassBalance the glacier mass balance model years : int year until which glacier evolution is calculated glen_a : float, optional Glen's parameter, (default: 2.4e-24 s^-1 Pa^-3) fs : float, optional sliding parameter, (default: 0) Returns ------- model : oggm.core.flowline.FluxBasedModel the initialized model TODO: return also length and volume steps (they are calculated for every time step) """ if not glen_a: glen_a = cfg.PARAMS['glen_a'] if not fs: fs = 0 model = FluxBasedModel(init_flowline, mb_model=mb_model, y0=0., glen_a=glen_a, fs=fs) # Year 0 to 600 in 5 years step yrs = np.arange(0, years, 5) # Array to fill with data nsteps = len(yrs) length = np.zeros(nsteps) vol = np.zeros(nsteps) # Loop for i, yr in enumerate(yrs): model.run_until(yr) length[i] = model.length_m vol[i] = model.volume_km3 return model # , length, vol
def test_find_flux_from_thickness(self): mb = LinearMassBalance(2600.) model = FluxBasedModel(dummy_constant_bed(), mb_model=mb) model.run_until(700) # Pick a flux and slope somewhere in the glacier for i in [1, 10, 20, 50]: flux = model.flux_stag[0][i] slope = model.slope_stag[0][i] thick = model.thick_stag[0][i] width = model.fls[0].widths_m[i] out = find_sia_flux_from_thickness(slope, width, thick) assert_allclose(out, flux, atol=1e-7)
def test_flux_gate_with_calving(self): mb = ScalarMassBalance() model = FluxBasedModel(dummy_constant_bed(), mb_model=mb, flux_gate_thickness=150, flux_gate_build_up=50, water_level=2000, is_tidewater=True) model.run_until(2000) assert_allclose(model.volume_m3 + model.calving_m3_since_y0, model.flux_gate_m3_since_y0) if do_plot: # pragma: no cover plt.plot(model.fls[-1].bed_h, 'k') plt.plot(model.fls[-1].surface_h, 'b') plt.show()
def progress_to_year(self, year): """Progress the glacier to year n. Parameters ---------- year: int Year until which to progress the glacier. """ # Some checks on the year. if year < 0: raise ValueError("Year has to be above zero") elif year <= self.age: warnings.warn( "Year has to be above the current age of" + " the glacier. It is not possible to" + " de-age the glacier." + " Geometry will remain." ) # If all passes else: # Check if we have a current state already. state = self._state() # Initialise the model model = FluxBasedModel( state, mb_model=self.mass_balance, y0=self.age, glen_a=self.creep, fs=self.basal_sliding, ) # Run the model. Store the history. try: out = model.run_until_and_store(year, fl_diag_path=None) # If it fails, see above. except RuntimeError: print("Glacier grew out of its domain, stepping back five years") # Ohhh recursion self.progress_to_year(year - 5) return # Update attributes. self.history = out[0] self.state_history = out[1][0] self._current_state = model.fls[0] self._model_state = model self.age = model.yr
def iterative_initial_glacier_search(gdir, y0=None, init_bias=0., rtol=0.005, write_steps=True): """Iterative search for the glacier in year y0. this is outdated and doesn't really work. """ fs = cfg.PARAMS['fs'] glen_a = cfg.PARAMS['glen_a'] if y0 is None: y0 = cfg.PARAMS['y0'] y1 = gdir.rgi_date.year mb = mbmods.PastMassBalance(gdir) fls = gdir.read_pickle('model_flowlines') model = FluxBasedModel(fls, mb_model=mb, y0=0., fs=fs, glen_a=glen_a) assert np.isclose(model.area_km2, gdir.rgi_area_km2, rtol=0.05) mb = mbmods.BackwardsMassBalanceModel(gdir) ref_area = gdir.rgi_area_m2 ite, bias, past_model = _find_inital_glacier(model, mb, y0, y1, rtol=rtol, init_bias=init_bias, ref_area=ref_area) path = gdir.get_filepath('model_run', delete=True) if write_steps: past_model.run_until_and_store(y1, path=path) else: past_model.to_netcdf(path)
def find_residual(gdir, a=-2000,b=2000): try: max_it = 15 i = 0 bounds = [a,b] df = pd.DataFrame() fls = gdir.read_pickle('model_flowlines') mod = FluxBasedModel(flowlines=fls) while i < max_it: bias = round((bounds[0] + bounds[1]) / 2,1) ex_mod2 = _run_experiment(gdir, bias) fit = fitness_function(ex_mod2,mod) df = df.append(pd.Series({'bias':bias,'fitness':fit}),ignore_index=True) if bounds[1]-bounds[0]<=1: break elif ex_mod2.area_km2 > mod.area_km2: bounds[0] = bias else: bounds[1] = bias i +=1 # best bias found bias = df.iloc[df.fitness.idxmin()].bias rp = gdir.get_filepath('model_run', filesuffix='_advanced_experiment_' + str(bias)) model = FileModel(rp) model.run_until(2000) rp = gdir.get_filepath('model_run', filesuffix='_advanced_experiment_' + str(0.0)) ex_mod = FileModel(rp) ex_mod.run_until(2000) plt.figure(figsize=(15,10)) plt.plot(model.fls[-1].surface_h,'r',label='best') plt.plot(mod.fls[-1].surface_h, 'orange', label='original') plt.plot(ex_mod.fls[-1].surface_h, 'r:', label='old experiment') plt.plot(model.fls[-1].bed_h,'k', label='bed') plt.legend() utils.mkdir(os.path.join(cfg.PATHS['plot_dir'],'bias_test')) plt.savefig(os.path.join(cfg.PATHS['plot_dir'],'bias_test',gdir.rgi_id+'.png'),dpi=200) plt.show() diff = mod.area_km2 - model.area_km2_ts()[2000] model.reset_y0(1865) series = pd.Series({'rgi_id':gdir.rgi_id,'bias':bias,'iterations':i, 'fitness':fit, 'area_diff':diff, 'model':model}) except: series = pd.Series({'rgi_id':gdir.rgi_id}) return series
def find_residual(gdir, temp_bias_list, ys, a=-2000, b=2000): for temp_bias in temp_bias_list: try: fls = gdir.read_pickle('model_flowlines') mod = FluxBasedModel(flowlines=fls) ye = gdir.rgi_date max_it = 15 i = 0 bounds = [a, b] df = pd.DataFrame() while i < max_it: bias = round((bounds[0] + bounds[1]) / 2, 2) ex_mod2 = _run_experiment(gdir, temp_bias, bias, ys, ye) if isinstance(ex_mod2, FileModel): diff = gdir.rgi_area_km2 - ex_mod2.area_km2_ts()[ye] error = '' # bias needs to be set higher else: diff = -np.inf error = ex_mod2.split(':')[-1] df = df.append(pd.Series({ 'bias': bias, 'area_diff': diff, 'error': error }), ignore_index=True) if (abs(diff) < 1e-4) or bounds[1] - bounds[0] <= 0.25: break elif diff < 0: bounds[0] = bias else: bounds[1] = bias i += 1 # best bias found bias = df.iloc[df.area_diff.abs().idxmin()].bias df.to_csv(os.path.join(gdir.dir, 'experiment_iteration.csv')) for file in os.listdir(gdir.dir): if file.startswith('model') and file.endswith( '.nc') and not file.endswith('_' + str(bias) + '.nc'): os.remove(os.path.join(gdir.dir, file)) except: pass
def read_result_parallel(gdir): try: ye = gdir.rgi_date fls = gdir.read_pickle('model_flowlines') mod = FluxBasedModel(flowlines=fls) lec = get_ref_length_data(gdir).dL if lec.index[0] < 1917: lec.loc[1917] = np.nan lec = lec.sort_index().interpolate() lec = lec - lec.loc[1917] lec = lec[lec.index >=1917] ''' lec = lec[lec.index <= ye] lec = (lec - lec.iloc[-1]) + mod.length_m ini_df = pd.read_pickle(os.path.join(gdir.dir,'result1917.pkl'), compression='gzip') ini_df.loc[:,'fitness'] = pd.to_numeric(ini_df.fitness / 125) ini_df = ini_df.dropna(subset=['fitness']) med_mod, perc_min, perc_max = find_median(ini_df) temp_bias = cfg.PATHS['working_dir'].split('_')[-1] #return pd.Series({'rgi':gdir.rgi_id, 'temp_bias':temp_bias, 'median':med_mod}) lec.loc[1917] = np.nan lec = lec.sort_index().interpolate()[lec.index >= 1917] lec.loc['rgi_id']= gdir.rgi_id print(med_mod.length_m_ts()[lec.index]) rmse = np.sqrt(((lec - med_mod.length_m_ts(rollmin=5)[lec.index]) ** 2).mean()) error = (lec - med_mod.length_m_ts(rollmin=5)[lec.index]).mean() max = (lec - med_mod.length_m_ts(rollmin=5)[lec.index]).max() min = (lec - med_mod.length_m_ts(rollmin=5)[lec.index]).min() if abs(max)>abs(min): max_diff = max else: max_diff = min # saves median state, minimum state and experiment model return pd.Series({'rgi':gdir.rgi_id,'region':gdir.rgi_region, 'length':mod.length_m, 'temp_bias':temp_bias, 'rmse':rmse, 'max_diff':max_diff, 'error':error}) ''' lec.loc['rgi'] = gdir.rgi_id return lec except: return pd.Series({'rgi':gdir.rgi_id})
def run_model(param, gdir): nx = y_1900.fls[-1].nx fls = gdir.read_pickle('model_flowlines') surface_h = rescale(param, nx) thick = surface_h - y_1900.fls[-1].bed_h # We define the length a bit differently: but more robust try: pok = np.where(thick < 10)[0] surface_h[int(pok[0]):] = y_1900.fls[-1].bed_h[int(pok[0]):] fls[-1].surface_h = surface_h real_model = FluxBasedModel(fls, mb_model=past_climate, glen_a=cfg.A, y0=1850) model = copy.deepcopy(real_model) real_model.run_until(1900) return [model, real_model] except: pass
def find_residual(gdir, temp_bias_list, ys,a=-2000,b=2000): best_df = pd.DataFrame() fls = gdir.read_pickle('model_flowlines') mod = FluxBasedModel(flowlines=fls) for temp_bias in temp_bias_list: try: ye = gdir.rgi_date max_it = 15 i = 0 bounds = [a,b] df = pd.DataFrame() while i < max_it: bias = round((bounds[0] + bounds[1]) / 2,1) ex_mod2 = _run_experiment(gdir, temp_bias, bias, ys, ye) diff = mod.area_km2 - ex_mod2.area_km2_ts()[ye] df = df.append(pd.Series({'bias':bias,'area_diff':diff}),ignore_index=True) if (abs(diff)<1e-4) or bounds[1]-bounds[0]<=1: break elif ex_mod2.area_km2_ts()[ye] > mod.area_km2: bounds[0] = bias else: bounds[1] = bias i +=1 # best bias found bias = df.iloc[df.area_diff.abs().idxmin()].bias rp = gdir.get_filepath('model_run', filesuffix='_advanced_experiment_'+str(temp_bias)+'_'+str(bias)) model = FileModel(rp) diff = gdir.rgi_area_km2 - model.area_km2_ts()[gdir.rgi_date] series = pd.Series({'rgi_id':gdir.rgi_id,'bias':bias,'iterations':i, 'area_diff':diff, 'model':model, 'temp_bias':temp_bias}) except: series = pd.Series({'rgi_id':gdir.rgi_id, 'temp_bias':temp_bias}) best_df = best_df.append(series, ignore_index=True) return best_df
def run_model(param, gdir, ela): climate = LinearMassBalance(ela_h=ela) climate.temp_bias = param fls = gdir.read_pickle('model_flowlines') fls1 = copy.deepcopy(fls) fls1[-1].surface_h = y_start.fls[-1].surface_h model = FluxBasedModel(fls1, mb_model=climate, glen_a=cfg.A, y0=0) model.run_until(50) fls2 = copy.deepcopy(fls) fls2[-1].surface_h = copy.deepcopy(model.fls[-1].surface_h) real_model = FluxBasedModel(fls2, mb_model=past_climate, glen_a=cfg.A, y0=1850) real_model.run_until(1900) return [model, real_model]
def run_model(param,gdir,fls): fls1 = copy.deepcopy(fls) climate = random_climate2 climate.temp_bias = param model = FluxBasedModel(fls1, mb_model=climate, y0=1890) model.run_until_equilibrium() # fls2= copy.deepcopy(fls) fls2 = model.fls real_model = FluxBasedModel(fls2, mb_model=past_climate, glen_a=cfg.A, y0=1850) real_model.run_until(2000) return [model,real_model]
def spinup_run(t_bias): # with t_bias the glacier state after spinup is changed between iterations mb_spinup.temp_bias = t_bias # run the spinup model_spinup = FluxBasedModel(copy.deepcopy(fls_spinup), mb_spinup, y0=0) model_spinup.run_until_equilibrium(max_ite=1000) # Now conduct the actual model run to the rgi date model_historical = FluxBasedModel(model_spinup.fls, mb_historical, y0=yr_spinup) model_historical.run_until(yr_rgi) cost = (model_historical.length_m - length_m_ref) / length_m_ref * 100 return cost
def test_water_level(self, default_calving): _, ds_1, _ = default_calving model = FluxBasedModel(bu_tidewater_bed(water_level=1000), mb_model=ScalarMassBalance(), is_tidewater=True, calving_use_limiter=True, flux_gate=0.06, do_kcalving=True, calving_water_level=1000, calving_k=0.2) _, ds_2 = model.run_until_and_store(3000) assert_allclose(model.volume_m3 + model.calving_m3_since_y0, model.flux_gate_m3_since_y0) assert_allclose(ds_1.calving_m3, ds_2.calving_m3) if do_plot: df_diag = model.get_diagnostics() f, ax = plt.subplots(1, 1, figsize=(12, 5)) df_diag[['surface_h', 'bed_h']].plot(ax=ax, color=['C3', 'k']) plt.hlines(1000, 0, 60000, color='C0', linestyles=':') plt.ylim(1000 - 350, 1000 + 800) plt.ylabel('Altitude [m]') plt.show() # Let the model decide the water level fls = bu_tidewater_bed(water_level=1000) thick = fls[0].thick thick[fls[0].bed_h > 1000] = 1 fls[0].thick = thick model = FluxBasedModel(fls, mb_model=ScalarMassBalance(), is_tidewater=True, calving_use_limiter=True, is_lake_terminating=True, flux_gate=0.06, do_kcalving=True, calving_k=0.2) assert_allclose(model.water_level, 1000, atol=1) with pytest.raises(InvalidParamsError): fls = bu_tidewater_bed(water_level=1000) FluxBasedModel(fls, mb_model=ScalarMassBalance(), is_tidewater=True, calving_use_limiter=True, is_lake_terminating=True)
def run_model(param, gdir, fls, random_climate2): fls1 = copy.deepcopy(fls) climate = random_climate2 climate.temp_bias = param model = FluxBasedModel(fls1, mb_model=climate, y0=1890) model.run_until_equilibrium() fls2 = copy.deepcopy(fls) #fls2 = model.fls for i in range(len(fls)): fls2[i].surface_h = model.fls[i].surface_h real_model = FluxBasedModel(fls2, mb_model=past_climate, glen_a=cfg.A, y0=1850) real_model.run_until(2000) return [model, real_model]
def test_simple_flux_gate(self): mb = ScalarMassBalance() model = FluxBasedModel(dummy_constant_bed(), mb_model=mb, flux_gate_thickness=150, flux_gate_build_up=50) model.run_until(1000) assert_allclose(model.volume_m3, model.flux_gate_m3_since_y0) model = FluxBasedModel(dummy_mixed_bed(), mb_model=mb, flux_gate_thickness=150, flux_gate_build_up=50) model.run_until(1000) assert_allclose(model.volume_m3, model.flux_gate_m3_since_y0) # Make sure that we cover the types of beds beds = np.unique(model.fls[0].shape_str[model.fls[0].thick > 0]) assert len(beds) == 2 if do_plot: # pragma: no cover plt.plot(model.fls[-1].bed_h, 'k') plt.plot(model.fls[-1].surface_h, 'b') plt.show()
def plot_advanced_experiment(gdir): fig = plt.figure(figsize=(15, 14)) grid = plt.GridSpec(1, 2, hspace=0.2, wspace=0.2) ax1 = plt.subplot(grid[0]) ax2 = plt.subplot(grid[1], sharey=ax1) ax2.plot(gdir.rgi_date,gdir.rgi_area_km2,'o', label='RGI area '+ str(gdir.rgi_date)) mod = FluxBasedModel(flowlines=gdir.read_pickle('model_flowlines')) ax2.plot(gdir.rgi_date, mod.area_km2, 'o', label='RGI area ' + str(gdir.rgi_date)) for f in os.listdir(gdir.dir): if f.startswith('model_run_'): rp = os.path.join(gdir.dir,f) model = FileModel(rp) model.area_km2_ts().plot(ax=ax2, label=f) #ax2.set_xlim((1915,2005)) #ax2.legend() plt.show()
def run_model(surface_h): nx = y1.fls[-1].nx random_climate = pickle.load(open('random_climate_hef.pkl', 'rb')) hef_fls = pickle.load(open('hef_y1.pkl', 'rb')) surface_h = rescale(surface_h, nx) thick = surface_h - hef_fls[-1].bed_h # We define the length a bit differently: but more robust try: pok = np.where(thick < 10)[0] surface_h[int(pok[0]):] = hef_fls[-1].bed_h[int(pok[0]):] except: pass hef_fls[-1].surface_h = surface_h commit_model = FluxBasedModel(hef_fls, mb_model=random_climate, glen_a=cfg.A, y0=1850) return commit_model
def test_random(self): # Fake Reset (all these tests are horribly coded) if not os.path.exists(TEST_DIR): os.makedirs(TEST_DIR) with open(CLI_LOGF, 'wb') as f: pickle.dump('none', f) gdirs = up_to_inversion(reset=False) # First tests df = utils.compile_glacier_statistics(gdirs) df['volume_before_calving_km3'] = df['volume_before_calving'] * 1e-9 assert np.sum(~df.volume_before_calving.isnull()) == 2 dfs = df.iloc[:2] assert np.all(dfs['volume_before_calving_km3'] < dfs['inv_volume_km3']) assert_allclose(df['inv_flowline_glacier_area'] * 1e-6, df['rgi_area_km2']) workflow.execute_entity_task(flowline.init_present_time_glacier, gdirs) # Check init_present_time_glacier not messing around too much for gd in gdirs: from oggm.core.massbalance import LinearMassBalance from oggm.core.flowline import FluxBasedModel mb_mod = LinearMassBalance(ela_h=2500) fls = gd.read_pickle('model_flowlines') model = FluxBasedModel(fls, mb_model=mb_mod) df.loc[gd.rgi_id, 'start_area_km2'] = model.area_km2 df.loc[gd.rgi_id, 'start_volume_km3'] = model.volume_km3 df.loc[gd.rgi_id, 'start_length'] = model.length_m assert_allclose(df['rgi_area_km2'], df['start_area_km2'], rtol=0.01) assert_allclose(df['rgi_area_km2'].sum(), df['start_area_km2'].sum(), rtol=0.005) assert_allclose(df['inv_volume_km3'], df['start_volume_km3']) assert_allclose(df['inv_volume_km3'].sum(), df['start_volume_km3'].sum()) assert_allclose(df['main_flowline_length'], df['start_length']) workflow.execute_entity_task(flowline.run_random_climate, gdirs, nyears=100, seed=0, store_monthly_step=True, output_filesuffix='_test') for gd in gdirs: path = gd.get_filepath('model_run', filesuffix='_test') # See that we are running ok with flowline.FileModel(path) as model: vol = model.volume_km3_ts() area = model.area_km2_ts() length = model.length_m_ts() self.assertTrue(np.all(np.isfinite(vol) & vol != 0.)) self.assertTrue(np.all(np.isfinite(area) & area != 0.)) self.assertTrue(np.all(np.isfinite(length) & length != 0.)) ds_diag = gd.get_filepath('model_diagnostics', filesuffix='_test') ds_diag = xr.open_dataset(ds_diag) df = vol.to_frame('RUN') df['DIAG'] = ds_diag.volume_m3.to_series() * 1e-9 assert_allclose(df.RUN, df.DIAG) df = area.to_frame('RUN') df['DIAG'] = ds_diag.area_m2.to_series() * 1e-6 assert_allclose(df.RUN, df.DIAG) df = length.to_frame('RUN') df['DIAG'] = ds_diag.length_m.to_series() assert_allclose(df.RUN, df.DIAG) # Test output ds = utils.compile_run_output(gdirs, input_filesuffix='_test') assert_allclose(ds_diag.volume_m3, ds.volume.sel(rgi_id=gd.rgi_id)) assert_allclose(ds_diag.area_m2, ds.area.sel(rgi_id=gd.rgi_id)) assert_allclose(ds_diag.length_m, ds.length.sel(rgi_id=gd.rgi_id)) df = ds.volume.sel(rgi_id=gd.rgi_id).to_series().to_frame('OUT') df['RUN'] = ds_diag.volume_m3.to_series() assert_allclose(df.RUN, df.OUT) # Compare to statistics df = utils.compile_glacier_statistics(gdirs) df['y0_vol'] = ds.volume.sel(rgi_id=df.index, time=0) * 1e-9 df['y0_area'] = ds.area.sel(rgi_id=df.index, time=0) * 1e-6 df['y0_len'] = ds.length.sel(rgi_id=df.index, time=0) assert_allclose(df['rgi_area_km2'], df['y0_area'], 0.06) assert_allclose(df['inv_volume_km3'], df['y0_vol'], 0.04) assert_allclose(df['main_flowline_length'], df['y0_len']) # Calving stuff assert ds.isel(rgi_id=0).calving[-1] > 0 assert ds.isel(rgi_id=0).calving_rate[-1] > 0 assert ds.isel(rgi_id=0).volume_bsl[-1] == 0 assert ds.isel(rgi_id=0).volume_bwl[-1] > 0 assert ds.isel(rgi_id=1).calving[-1] > 0 assert ds.isel(rgi_id=1).calving_rate[-1] > 0 assert not np.isfinite(ds.isel(rgi_id=1).volume_bsl[-1])
def plot_median(gdir, df, eps, ex_mod, ys, ye, lec, plot_dir): plot_dir = os.path.join(plot_dir, '04_median') utils.mkdir(plot_dir) x = np.arange(ex_mod.fls[-1].nx) * ex_mod.fls[-1].dx * ex_mod.fls[ -1].map_dx fig = plt.figure(figsize=(25, 18)) grid = plt.GridSpec(2, 2, hspace=0.2, wspace=0.2) ax1 = plt.subplot(grid[0, 0]) ax2 = plt.subplot(grid[0, 1], sharey=ax1) ax3 = plt.subplot(grid[1, :]) if gdir.name != '': plt.suptitle(gdir.rgi_id + ': ' + gdir.name, fontsize=30) elif gdir.rgi_id.endswith('779'): plt.suptitle(gdir.rgi_id + ': Guslarferner', fontsize=30) else: plt.suptitle(gdir.rgi_id, fontsize=30) df = df.sort_values('fitness', ascending=False) # min model min_mod = deepcopy(df.loc[df.fitness.idxmin(), 'model']) min_mod.length_m_ts(rollmin=5).plot(ax=ax3, color='C1', linewidth=3, label=r'$s_{' + str(ys) + '-' + str( ye) + '}^{min}$') min_mod.reset_y0(ys) min_mod.run_until(ys) # real flowlines fls = gdir.read_pickle('model_flowlines') mod = FluxBasedModel(flowlines=fls) ax2.plot(x, mod.fls[-1].surface_h, 'C2', label=r'OGGM$_{init}$') ax1.plot(x, min_mod.fls[-1].surface_h, 'C1', label=r'$z_{' + str(ys) + '}^{min}$', linewidth=3) min_mod.run_until(ye) ax2.plot(x, min_mod.fls[-1].surface_h, 'C1', label=r'$z_{2000}^{min}$', linewidth=3) # acceptable glacier states df = df[df.fitness <=1] s_t0 = pd.DataFrame() s_te = pd.DataFrame() v = pd.DataFrame() for i in df.index: model = deepcopy(df.loc[i, 'model']) s_t0 = s_t0.append(pd.Series(model.fls[-1].surface_h), ignore_index=True) model.run_until(ye) s_te = s_te.append(pd.Series(model.fls[-1].surface_h), ignore_index=True) v = v.append(model.length_m_ts(rollmin=5), ignore_index=True) ax1.fill_between(x, s_t0.max().values, s_t0.min().values, alpha=0.3, color='grey', label=r'$\mathcal{S}_{' + str(ys) + '}^{' + str( eps) + '}$') ax2.fill_between(x, s_te.max().values, s_te.min().values, alpha=0.3, color='grey', label=r'$\mathcal{S}_{' + str(ye) + '}^{' + str( eps) + '}$') ax3.fill_between(model.length_m_ts(rollmin=5).index, v.max().values, v.min().values, alpha=0.3, color='grey', label=r'$\mathcal{S}_{' +str(ys)+'-'+str(ye) +'}^{' + str(eps) + '}$') # 5% quantile and median of 5% quantile df = df[df.fitness <= df.fitness.quantile(0.05)] s_t0 = pd.DataFrame() s_te = pd.DataFrame() v = pd.DataFrame() for i in df.index: model = deepcopy(df.loc[i, 'model']) s_t0 = s_t0.append(pd.Series(model.fls[-1].surface_h), ignore_index=True) model.run_until(ye) s_te = s_te.append(pd.Series(model.fls[-1].surface_h), ignore_index=True) v = v.append(model.length_m_ts(rollmin=5), ignore_index=True) ax1.fill_between(x, s_t0.max().values, s_t0.min().values, alpha=0.5, label=r'$Q_{0.05}(\mathcal{S}_{'+str(ys)+'}^{'+str(eps)+'})$') ax2.fill_between(x, s_te.max().values, s_te.min().values, alpha=0.5, label=r'$Q_{0.05}(\mathcal{S}_{'+str(ye)+'}^{'+str(eps)+'})$') ax3.fill_between(v.columns, v.max().values, v.min().values, alpha=0.5, linewidth=3, label=r'$Q_{0.05}(\mathcal{S}_{'+str(ys)+'-'+str(ye)+'}^{'+str(eps)+'})$') # median of 5% quantile df.loc[:, 'length'] = df.model.apply(lambda x: x.length_m) df = df.sort_values('length', ascending=False) l = len(df) if l % 2: index = int((l - 1) / 2) else: index = int(l / 2) median_model = deepcopy(df.iloc[index].model) median_model.length_m_ts(rollmin=5).plot(ax=ax3, linewidth=3, label=r'$s_{'+str(ys)+'-'+str(ye)+'}^{med}$') median_model.reset_y0(ys) median_model.run_until(ys) ax1.plot(x, median_model.fls[-1].surface_h, label=r'$z_{'+str(ys)+'}^{med}$', linewidth=3) median_model.run_until(ye) ax2.plot(x, median_model.fls[-1].surface_h, label=r'$z_{'+str(ye)+'}^{med}$', linewidth=3) # experiment lec.plot(ax=ax3, color='r', linewidth=3, label='Leclercq') ax1.plot(x, ex_mod.fls[-1].bed_h, 'k', label=r'$b$', linewidth=3) ax2.plot(x, ex_mod.fls[-1].bed_h, 'k', label=r'$b$', linewidth=3) #ex_mod.length_m_ts(rollmin=5).plot(ax=ax3, color='k') # add figure names and x-/ylabels add_at(ax1, r"a", loc=3) add_at(ax2, r"b", loc=3) add_at(ax3, r"c", loc=3) ax1.set_ylabel('Altitude (m)', fontsize=30) ax1.set_xlabel('Distance along the main flowline (m)', fontsize=30) ax2.set_ylabel('Altitude (m)', fontsize=30) ax2.set_xlabel('Distance along the main flowline (m)', fontsize=30) ax3.set_ylabel(r'Length ($m$)', fontsize=30) ax3.set_xlabel('Time (years)', fontsize=30) ax1.tick_params(axis='both', which='major', labelsize=30) ax2.tick_params(axis='both', which='major', labelsize=30) ax3.tick_params(axis='both', which='major', labelsize=30) ax3.yaxis.offsetText.set_fontsize(30) ax3.set_xlim(xmin=1915, xmax=2019) l1 = ax1.legend(loc=1, fontsize=25) l1.set_zorder(1) l2 = ax2.legend(loc=1, fontsize=25) l2.set_zorder(1) l3 = ax3.legend(loc=1, fontsize=25) l3.set_zorder(1) fig_name = 'median_'+str(ys)+'_'+gdir.rgi_id plt.savefig(os.path.join(plot_dir, fig_name+'.pdf'), dpi=300) plt.savefig(os.path.join(plot_dir, fig_name+'.png'), dpi=300) plt.show() plt.close()
def test_constant_bed(self): map_dx = 100. yrs = np.arange(1, 400, 5) lens = [] volume = [] areas = [] surface_h = [] # Flowline case fls = dummy_constant_bed(hmax=3000., hmin=1000., nx=200, map_dx=map_dx, widths=1.) mb = LinearMassBalance(2600.) flmodel = FluxBasedModel(fls, mb_model=mb, y0=0.) length = yrs * 0. vol = yrs * 0. area = yrs * 0 for i, y in enumerate(yrs): flmodel.run_until(y) length[i] = fls[-1].length_m vol[i] = fls[-1].volume_km3 area[i] = fls[-1].area_km2 lens.append(length) volume.append(vol) areas.append(area) surface_h.append(fls[-1].surface_h.copy()) # Make a 2D bed out of the 1D bed_2d = np.repeat(fls[-1].bed_h, 3).reshape((fls[-1].nx, 3)) sdmodel = Upstream2D(bed_2d, dx=map_dx, mb_model=mb, y0=0., ice_thick_filter=None) length = yrs * 0. vol = yrs * 0. area = yrs * 0 for i, y in enumerate(yrs): sdmodel.run_until(y) surf_1d = sdmodel.ice_thick[:, 1] length[i] = np.sum(surf_1d > 0) * sdmodel.dx vol[i] = sdmodel.volume_km3 / 3 area[i] = sdmodel.area_km2 / 3 lens.append(length) volume.append(vol) areas.append(area) surface_h.append(sdmodel.surface_h[:, 1]) if do_plot: plt.figure() plt.plot(yrs, lens[0], 'r') plt.plot(yrs, lens[1], 'b') plt.title('Compare Length') plt.xlabel('years') plt.ylabel('[m]') plt.legend(['Flowline', '2D'], loc=2) plt.figure() plt.plot(yrs, volume[0], 'r') plt.plot(yrs, volume[1], 'b') plt.title('Compare Volume') plt.xlabel('years') plt.ylabel('[km^3]') plt.legend(['Flowline', '2D'], loc=2) plt.figure() plt.plot(fls[-1].bed_h, 'k') plt.plot(surface_h[0], 'r') plt.plot(surface_h[1], 'b') plt.title('Compare Shape') plt.xlabel('[m]') plt.ylabel('Elevation [m]') plt.legend(['Bed', 'Flowline', '2D'], loc=2) plt.show() np.testing.assert_almost_equal(lens[0][-1], lens[1][-1]) np.testing.assert_allclose(volume[0][-1], volume[1][-1], atol=3e-3) self.assertTrue(utils.rmsd(lens[0], lens[1]) < 50.) self.assertTrue(utils.rmsd(volume[0], volume[1]) < 2e-3) self.assertTrue(utils.rmsd(areas[0], areas[1]) < 2e-3) self.assertTrue(utils.rmsd(surface_h[0], surface_h[1]) < 1.0) # Equilibrium sdmodel.run_until_equilibrium() flmodel.run_until_equilibrium() assert_allclose(sdmodel.volume_km3 / 3, flmodel.volume_km3, atol=2e-3) assert_allclose(sdmodel.area_km2 / 3, flmodel.area_km2, atol=2e-3) # Store run_ds = sdmodel.run_until_and_store(sdmodel.yr+50) ts = run_ds['ice_thickness'].mean(dim=['y', 'x']) assert_allclose(ts, ts.values[0], atol=1) # Other direction bed_2d = np.repeat(fls[-1].bed_h, 3).reshape((fls[-1].nx, 3)).T sdmodel = Upstream2D(bed_2d, dx=map_dx, mb_model=mb, y0=0., ice_thick_filter=None) length = yrs * 0. vol = yrs * 0. area = yrs * 0 for i, y in enumerate(yrs): sdmodel.run_until(y) surf_1d = sdmodel.ice_thick[1, :] length[i] = np.sum(surf_1d > 0) * sdmodel.dx vol[i] = sdmodel.volume_km3 / 3 area[i] = sdmodel.area_km2 / 3 lens.append(length) volume.append(vol) areas.append(area) surface_h.append(sdmodel.surface_h[:, 1]) np.testing.assert_almost_equal(lens[0][-1], lens[1][-1]) np.testing.assert_allclose(volume[0][-1], volume[1][-1], atol=3e-3) self.assertTrue(utils.rmsd(lens[0], lens[1]) < 50.) self.assertTrue(utils.rmsd(volume[0], volume[1]) < 2e-3) self.assertTrue(utils.rmsd(areas[0], areas[1]) < 2e-3) self.assertTrue(utils.rmsd(surface_h[0], surface_h[1]) < 1.0) # Equilibrium sdmodel.run_until_equilibrium() assert_allclose(sdmodel.volume_km3 / 3, flmodel.volume_km3, atol=2e-3) assert_allclose(sdmodel.area_km2 / 3, flmodel.area_km2, atol=2e-3)