Skip to content

Commit ddd8b79

Browse files
committed
Optimize spinup run 0-year period with inversion dynamical run
1 parent c2027ea commit ddd8b79

1 file changed

Lines changed: 89 additions & 9 deletions

File tree

pygem/bin/run/run_spinup.py

Lines changed: 89 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,17 @@
2020
# read the config
2121
pygem_prms = config_manager.read_config()
2222
from oggm import cfg, tasks, workflow
23-
from oggm.core.flowline import FluxBasedModel
23+
from oggm.core import flowline
2424

2525
import pygem.pygem_modelsetup as modelsetup
2626
from pygem import class_climate
2727
from pygem.massbalance import PyGEMMassBalance_wrapper
28-
29-
# from pygem.glacierdynamics import MassRedistributionCurveModel
3028
from pygem.oggm_compat import (
3129
single_flowline_glacier_directory,
3230
single_flowline_glacier_directory_with_calving,
3331
update_cfg,
3432
)
33+
from pygem.shop import debris
3534
from pygem.utils._funcs import interp1d_fill_gaps, str2bool
3635

3736

@@ -149,6 +148,79 @@ def run_spinup(gd, **kwargs):
149148
return out
150149

151150

151+
# run inversion at year 2000
152+
def run_inversion(gd, **kwargs):
153+
if gd.is_tidewater:
154+
cfg.PARAMS['use_kcalving_for_inversion'] = True
155+
tasks.find_inversion_calving_from_any_mb(
156+
gd,
157+
mb_model=PyGEMMassBalance_wrapper(
158+
gd,
159+
fl_str='inversion_flowlines',
160+
option_areaconstant=True,
161+
),
162+
glen_a=gd.get_diagnostics().get('inversion_glen_a', None),
163+
fs=gd.get_diagnostics().get('inversion_fs', None),
164+
)
165+
else:
166+
cfg.PARAMS['use_kcalving_for_inversion'] = False
167+
tasks.prepare_for_inversion(gd)
168+
tasks.mass_conservation_inversion(
169+
gd,
170+
glen_a=gd.get_diagnostics().get('inversion_glen_a', None),
171+
fs=gd.get_diagnostics().get('inversion_fs', None),
172+
)
173+
# create the dynamic flowlines
174+
workflow.execute_entity_task(tasks.init_present_time_glacier, [gd])
175+
176+
# add debris to model_flowlines
177+
workflow.execute_entity_task(debris.debris_binned, [gd], fl_str='model_flowlines')
178+
179+
return _run_oggm_dynamics(gd, **kwargs)
180+
181+
182+
def _run_oggm_dynamics(gd, **kwargs):
183+
"""run the dynamical evolution model with a given set of model parameters"""
184+
y0 = 2000
185+
y1 = gd.dates_table.year.max()
186+
fls = gd.read_pickle('model_flowlines')
187+
# mass balance model with evolving area
188+
mbmod = PyGEMMassBalance_wrapper(
189+
gd,
190+
fl_str='model_flowlines',
191+
)
192+
193+
# glacier dynamics model
194+
if gd.is_tidewater and pygem_prms['setup']['include_frontalablation']:
195+
ev_model = flowline.FluxBasedModel(
196+
fls,
197+
y0=y0,
198+
mb_model=mbmod,
199+
glen_a=gd.get_diagnostics()['inversion_glen_a'],
200+
fs=gd.get_diagnostics()['inversion_fs'],
201+
is_tidewater=gd.is_tidewater,
202+
water_level=gd.get_diagnostics().get('calving_water_level', None),
203+
do_kcalving=pygem_prms['setup']['include_frontalablation'],
204+
)
205+
else:
206+
ev_model = flowline.SemiImplicitModel(
207+
fls,
208+
y0=y0,
209+
mb_model=mbmod,
210+
glen_a=gd.get_diagnostics()['inversion_glen_a'],
211+
fs=gd.get_diagnostics()['inversion_fs'],
212+
)
213+
try:
214+
# run glacier dynamics model forward
215+
ev_model.run_until_and_store(
216+
y1 + 1, fl_diag_path=gd.get_filepath('fl_diagnostics', filesuffix='_dynamic_spinup_pygem_mb')
217+
)
218+
return [ev_model]
219+
# safely catch any errors with dynamical run
220+
except Exception:
221+
return [None]
222+
223+
152224
def run(glacno_list, mb_model_params, optimize=False, periods2try=[20], outdir=None, debug=False, ncores=1, **kwargs):
153225
# remove any None kwargs
154226
kwargs = {k: v for k, v in kwargs.items() if v is not None}
@@ -196,7 +268,7 @@ def run(glacno_list, mb_model_params, optimize=False, periods2try=[20], outdir=N
196268
gd.is_tidewater = True
197269
if kwargs['allow_calving']:
198270
kwargs['evolution_model'] = partial(
199-
FluxBasedModel, water_level=gd.get_diagnostics().get('calving_water_level', None)
271+
flowline.FluxBasedModel, water_level=gd.get_diagnostics().get('calving_water_level', None)
200272
) # use FluxBasedModel to allow for calving
201273
cfg.PARAMS['use_kcalving_for_inversion'] = True
202274
cfg.PARAMS['use_kcalving_for_run'] = True
@@ -296,7 +368,7 @@ def run(glacno_list, mb_model_params, optimize=False, periods2try=[20], outdir=N
296368
############################
297369

298370
# update cfg.PARAMS
299-
update_cfg({'continue_on_error': True}, 'PARAMS')
371+
update_cfg({'continue_on_error': False}, 'PARAMS')
300372
update_cfg({'store_model_geometry': True}, 'PARAMS')
301373

302374
# optimize against binned dhdt data
@@ -317,12 +389,18 @@ def run(glacno_list, mb_model_params, optimize=False, periods2try=[20], outdir=N
317389

318390
# objective function to evaluate
319391
def _objective(**kwargs):
320-
fls = run_spinup(gd, **kwargs)
392+
if gd.rgi_date + 1 - kwargs['spinup_period'] >= 2000:
393+
fls = run_inversion(gd, **kwargs)
394+
else:
395+
fls = run_spinup(gd, **kwargs)
396+
321397
if fls[0] is None:
322398
return kwargs['spinup_period'], float('inf'), None
323399

324400
# get true spinup period (note, if initial fails, oggm tries period/2)
325401
spinup_period_ = gd.rgi_date + 1 - fls[0].y0
402+
if spinup_period_ in results.keys():
403+
return None
326404

327405
# create lookup dict (timestamp → index)
328406
dtable = modelsetup.datesmodelrun(startyear=fls[0].y0, endyear=kwargs['ye'])
@@ -339,7 +417,7 @@ def _objective(**kwargs):
339417
dhdt_hat = dh_hat / gd.elev_change_1d['nyrs']
340418

341419
# plot binned surface area
342-
ax.plot(dist, bin_area, label=f'{spinup_period} years: {round(1e-6 * np.sum(bin_area), 1)} km$^2$')
420+
ax.plot(dist, bin_area, label=f'{spinup_period_} years: {round(1e-6 * np.sum(bin_area), 1)} km$^2$')
343421

344422
# penalize positive values below specified elevation threshold
345423
loss = loss_with_penalty(
@@ -350,6 +428,8 @@ def _objective(**kwargs):
350428

351429
# evaluate candidate spinup periods
352430
for p in periods2try:
431+
if p in results.keys():
432+
continue
353433
kwargs['spinup_period'] = p
354434
p_, mismatch, model = _objective(**kwargs)
355435
results[p_] = (mismatch, model)
@@ -550,10 +630,10 @@ def main():
550630
'-periods2try',
551631
type=int,
552632
nargs='+',
553-
default=[20, 30, 40, 50, 60],
633+
default=[0, 10, 20, 30, 40, 50, 60],
554634
help=(
555635
'Optional list of spinup periods (years) to test if -optimize is used. '
556-
'Ignored otherwise. Example: -periods2try 20 30 40 50 60'
636+
'Ignored otherwise. Example: -periods2try 0 10 20 30 40 50 60'
557637
),
558638
)
559639
parser.add_argument(

0 commit comments

Comments
 (0)