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_parallel_experiment(gdir):

    # read flowlines from pre-processing
    fls = gdir.read_pickle('model_flowlines')
    try:
        # construct searched glacier
        # TODO: y0 in random mass balance?
        random_climate1 = RandomMassBalance(gdir, y0=1850, bias=0, seed=[1])
        random_climate1.temp_bias = -0.75
        commit_model = FluxBasedModel(fls, mb_model=random_climate1,
                                      glen_a=cfg.A, y0=1850)
        commit_model.run_until_equilibrium()
        y_t0 = deepcopy(commit_model)

    # try different seed of mass balance, if equilibrium could not be found
    except:

        # construct searched glacier
        random_climate1 = RandomMassBalance(gdir, y0=1850, bias=0,seed=[1])
        commit_model = FluxBasedModel(fls, mb_model=random_climate1,
                                      glen_a=cfg.A, y0=1850)
        commit_model.run_until_equilibrium()
        y_t0 = deepcopy(commit_model)

    # construct observed glacier
    past_climate = PastMassBalance(gdir)
    commit_model2 = FluxBasedModel(commit_model.fls, mb_model=past_climate,
                                   glen_a=cfg.A, y0=1850)
    commit_model2.run_until(2000)
    y_t = deepcopy(commit_model2)

    # save output in gdir_dir
    experiment = {'y_t0': y_t0, 'y_t': y_t,
                  'climate': random_climate1}
    gdir.write_pickle(experiment, 'synthetic_experiment')
Esempio n. 3
0
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 _run_parallel_experiment(gdir, t0, te):
    '''

    :param gdir:
    :param t0:
    :param te:
    :return:
    '''

    # read flowlines from pre-processing
    fls = gdir.read_pickle('model_flowlines')
    try:
        # construct searched glacier
        random_climate1 = RandomMassBalance(gdir, y0=t0, halfsize=14)

        #set temp bias negative to force a glacier retreat later
        random_climate1.temp_bias = -0.75
        commit_model = FluxBasedModel(fls,
                                      mb_model=random_climate1,
                                      glen_a=cfg.A,
                                      y0=t0)
        commit_model.run_until_equilibrium()
        y_t0 = deepcopy(commit_model)

    # try different seed of mass balance, if equilibrium could not be found
    except:

        # construct searched glacier
        random_climate1 = RandomMassBalance(gdir, y0=t0, halfsize=14)
        commit_model = FluxBasedModel(fls,
                                      mb_model=random_climate1,
                                      glen_a=cfg.A,
                                      y0=t0)
        commit_model.run_until_equilibrium()
        y_t0 = deepcopy(commit_model)

    # construct observed glacier
    past_climate = PastMassBalance(gdir)
    commit_model2 = FluxBasedModel(commit_model.fls,
                                   mb_model=past_climate,
                                   glen_a=cfg.A,
                                   y0=t0)
    commit_model2.run_until(te)
    y_t = deepcopy(commit_model2)

    # save output in gdir_dir
    experiment = {'y_t0': y_t0, 'y_t': y_t, 'climate': random_climate1}
    gdir.write_pickle(experiment, 'synthetic_experiment')
Esempio n. 5
0
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
Esempio n. 7
0
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]
Esempio n. 8
0
    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)
Esempio n. 9
0
def linear_mb_equilibrium(bed,
                          surface,
                          accw,
                          elaw,
                          nz,
                          mb_grad,
                          nx,
                          map_dx,
                          idx=None,
                          advance=None,
                          retreat=None,
                          plot=True):
    """Runs the OGGM FluxBasedModel with a linear mass balance
    gradient until the glacier reaches equilibrium.

    Parameters
    ----------
    bed : ndarray
        the glacier bed
    surface : ndarray
        the initial glacier surface
    accw : int
        the width of the glacier at the top of the accumulation area
    elaw : int
        the width of the glacier at the equilibrium line altitude
    nz : float
        fraction of vertical grid points occupied by accumulation area
    mb_grad : int, float
        the mass balance altitude gradient in mm w.e. m^-1 yr^-1
    nx : int
        number of grid points
    map_dx : int
        grid point spacing
    idx : int, optional
        number of vertical grid points to shift ELA down/upglacier
    advance : bool, optional
        move the ELA downglacier by idx grid points to simulate
        a glacier advance
    retreat : bool, optional
        move the ELA upglacier by idx grid points to simulate
        a glacier retreat
    plot : bool, optional
        show a pseudo-3d plot of the glacier (default: True)

    Returns
    -------
    model : oggm.core.flowline.FluxBasedModel
        OGGM model class of the glacier in equilibrium
    """

    # accumulation area occupies a fraction NZ of the total glacier extent
    acc_width = np.linspace(accw, elaw, int(nx * nz))

    # ablation area occupies a fraction 1 - NZ of the total glacier extent
    abl_width = np.tile(elaw, nx - len(acc_width))

    # glacier widths profile
    widths = np.hstack([acc_width, abl_width])

    # model widths
    mwidths = np.zeros(nx) + widths / map_dx

    # define the glacier bed
    init_flowline = RectangularBedFlowline(surface_h=surface,
                                           bed_h=bed,
                                           widths=mwidths,
                                           map_dx=map_dx)

    # equilibrium line altitude

    # in case of an advance scenario, move the ELA downglacier by a number of
    # vertical grid points idx
    if advance and idx:
        ela = bed[np.where(widths == elaw)[0][idx]]

    # in case of a retreat scenario, move the ELA upglacier by a number of
    # vertical grid points idx
    elif retreat and idx:
        ela = bed[np.where(widths == acc_width[-idx])[0][0]]

    # in case of no scenario, the ela is the height where the width of the ela
    # is first reached
    else:
        ela = bed[np.where(widths == elaw)[0][0]]

    # linear mass balance model
    mb_model = LinearMassBalance(ela, grad=mb_grad)

    # flowline model
    model = FluxBasedModel(init_flowline,
                           mb_model=mb_model,
                           y0=0.,
                           min_dt=0,
                           cfl_number=0.01)

    # run until the glacier reaches an equilibrium
    model.run_until_equilibrium()

    # show a pseudo-3d plot of the glacier geometry
    if plot:
        dis = distance_along_glacier(nx, map_dx)
        plot_glacier_3d(dis, bed, widths, nx)

    return model
Esempio n. 10
0
def response_time_vol(model, perturbed_mb):
    """Calculation of the volume response time after Oerlemans (1997).

    Parameters
    ----------
    model : oggm.core.flowline.FluxBasedModel
        OGGM model class of the glacier in equilibrium
    perturbed_mb : oggm.core.massbalance.LinearMassBalance
        Perturbed mass balance model

    Returns
    -------
    response_time : numpy.float64
        the response time of the glacier
    pert_model : oggm.core.flowline.FluxBasedModel
        OGGM model class of the glacier in equilibrium adapted to the new ELA
    """
    # to be sure that the model state is in equilibrium (maybe not necessary)
    count = 0
    while True:
        try:
            model.run_until_equilibrium(rate=0.006)
            break
        except RuntimeError:
            count += 1
            # if equilibrium not reached yet, add 1000 years. Then try again.
            model.run_until(models[0].yr + 1000)
            if count == 6:
                raise RuntimeError('Because the gradient is be very small, '
                                   'the equilibrium will be reached only '
                                   'after many years. Run this cell '
                                   'again, then it should work.')

    # set up new model, whith outlines of first model, but new mb_model
    pert_model = FluxBasedModel(model.fls[-1], mb_model=perturbed_mb, y0=0.)
    # run it until in reaches equilibrium state
    count = 0
    while True:
        try:
            pert_model.run_until_equilibrium(rate=0.006)
            break
        except RuntimeError:
            count += 1
            # if equilibrium not reached yet, add 1000 years. Then try again.
            pert_model.run_until(models[0].yr + 1000)
            if count == 6:
                raise RuntimeError('Because the gradient is be very small, '
                                   'the equilibrium will be reached only '
                                   'after many years. Run this cell '
                                   'again, then it should work.')

    # save outline of model in equilibrium state
    eq_pert_model = pert_model.fls[-1].surface_h
    # recalculate the perturbed model to be able to save intermediate steps
    yrs = np.arange(0, pert_model.yr, 5)
    nsteps = len(yrs)
    length_w = np.zeros(nsteps)
    vol_w = np.zeros(nsteps)
    year = np.zeros(nsteps)
    recalc_pert_model = FluxBasedModel(model.fls[-1],
                                       mb_model=perturbed_mb,
                                       y0=0.)
    for i, yer in enumerate(yrs):
        recalc_pert_model.run_until(yer)
        year[i] = recalc_pert_model.yr
        length_w[i] = recalc_pert_model.length_m
        vol_w[i] = recalc_pert_model.volume_km3
    # to get response time: calculate volume difference between model and pert.
    # model in eq. state
    vol_dif = recalc_pert_model.volume_km3
    vol_dif -= (recalc_pert_model.volume_km3 - model.volume_km3) / np.e
    # search for the appropriate time by determining the year with the closest
    # volume to vol_dif:
    # difference between volumes of different time steps and vol_dif
    all_dif_vol = abs(vol_w - vol_dif).tolist()
    # find index of smallest difference between
    index = all_dif_vol.index(min(all_dif_vol))
    response_time = year[index]

    return response_time, pert_model
Esempio n. 11
0
# Figure
f = 0.7
f, axs = plt.subplots(2, 2, figsize=(10 * f, 7 * f), sharey=True, sharex=True)
axs = np.asarray(axs).flatten()

tx, ty = .98, .97
letkm = dict(color='black',
             ha='right',
             va='top',
             fontsize=12,
             bbox=dict(facecolor='white', edgecolor='black'))

fls = dummy_constant_bed(map_dx=gdir.grid.dx)
mb = LinearMassBalance(2600.)
model = FluxBasedModel(fls, mb_model=mb, y0=0.)
model.run_until_equilibrium()
fls = []
for fl in model.fls:
    pg = np.where(fl.thick > 0)
    line = shpg.LineString([fl.line.coords[int(p)] for p in pg[0]])
    flo = Centerline(line, dx=fl.dx, surface_h=fl.surface_h[pg])
    flo.widths = fl.widths[pg]
    flo.is_rectangular = np.ones(flo.nx).astype(np.bool)
    fls.append(flo)

gdir.write_pickle(fls, 'inversion_flowlines')
tasks.apparent_mb_from_linear_mb(gdir)
tasks.prepare_for_inversion(gdir)
v, _ = mass_conservation_inversion(gdir)
np.testing.assert_allclose(v, model.volume_m3, rtol=0.05)
inv = gdir.read_pickle('inversion_output')[-1]
Esempio n. 12
0
def find_initial_state(gdir):

    global past_climate,random_climate2
    global y_2000

    global x
    global ax1,ax2,ax3

    fls = gdir.read_pickle('model_flowlines')
    past_climate = PastMassBalance(gdir)
    random_climate1 = RandomMassBalance(gdir,y0=1865,halfsize=14)


    #construct searched glacier
    commit_model = FluxBasedModel(fls, mb_model=random_climate1,
                                  glen_a=cfg.A, y0=1850)
    commit_model.run_until_equilibrium()
    y_1880 = copy.deepcopy(commit_model)

    #construct observed glacier
    commit_model2 = FluxBasedModel(commit_model.fls, mb_model=past_climate,
                                  glen_a=cfg.A, y0=1880)
    commit_model2.run_until(2000)
    y_2000 = copy.deepcopy(commit_model2)

    results  = pd.DataFrame(columns=['1880','2000','length_1880'])

    for i in range(4):
        random_climate2 = RandomMassBalance(gdir, y0=1875, halfsize=14)
        res = minimize(objfunc, [0], args=(gdir, y_2000.fls),
                       method='COBYLA',
                       tol=1e-04, options={'maxiter': 100, 'rhobeg': 1})
        #try:
        result_model_1880, result_model_2000 = run_model(res.x, gdir,
                                                         y_2000.fls)
        results = results.append({'1880':result_model_1880,'2000':result_model_2000,'length_1880':result_model_1880.length_m,'length_2000':result_model_2000.length_m}, ignore_index=True)
        #except:
        #   pass

    # create plots
    for i in range(len(fls)):
        plt.figure(i,figsize=(20,10))
        #add subplot in the corner
        fig, ax1 = plt.subplots(figsize=(20, 10))
        ax2 = fig.add_axes([0.55, 0.66, 0.3, 0.2])
        ax1.set_title(gdir.rgi_id+' flowline '+str(i))
        box = ax1.get_position()
        ax1.set_position([box.x0, box.y0, box.width * 0.95, box.height])

        x = np.arange(y_2000.fls[i].nx) * y_2000.fls[i].dx * y_2000.fls[i].map_dx
        for j in range(len(results)):
            ax1.plot(x, results.get_value(j, '1880').fls[i].surface_h, alpha=0.8, )
            ax2.plot(x, results.get_value(j, '2000').fls[i].surface_h, alpha=0.8, )

        ax1.plot(x,y_1880.fls[i].surface_h,'k:')
        ax2.plot(x, y_2000.fls[i].surface_h, 'k')

        ax1.plot(x, y_1880.fls[i].bed_h, 'k')
        ax2.plot(x, y_2000.fls[i].bed_h, 'k')

        plot_dir = os.path.join(cfg.PATHS['working_dir'], 'plots')
        plt.savefig(os.path.join(plot_dir, gdir.rgi_id +'_fls'+str(i)+ '.png'))
    #plt.show()

    results.to_csv(os.path.join(plot_dir,str(gdir.rgi_id)+'.csv'))
    '''
Esempio n. 13
0
    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)
Esempio n. 14
0
def find_initial_state(gdir):

    global past_climate, random_climate2
    global y_2000

    global x
    global ax1, ax2, ax3

    fls = gdir.read_pickle('model_flowlines')
    past_climate = PastMassBalance(gdir)
    random_climate1 = RandomMassBalance(gdir, y0=1865, halfsize=14)

    #construct searched glacier
    commit_model = FluxBasedModel(fls,
                                  mb_model=random_climate1,
                                  glen_a=cfg.A,
                                  y0=1850)
    commit_model.run_until_equilibrium()
    y_1880 = copy.deepcopy(commit_model)

    #construct observed glacier
    commit_model2 = FluxBasedModel(commit_model.fls,
                                   mb_model=past_climate,
                                   glen_a=cfg.A,
                                   y0=1880)
    commit_model2.run_until(2000)
    y_2000 = copy.deepcopy(commit_model2)

    results = pd.DataFrame(columns=['1880', '2000', 'length_1880'])

    pool = mp.Pool()
    result_list = pool.map(partial(run_parallel, gdir=gdir, y_2000=y_2000),
                           range(300))
    pool.close()
    pool.join()
    result_list = [x for x in result_list if x != [None, None]]
    # create plots
    for i in range(len(result_list[0][0].fls)):
        plt.figure(i, figsize=(20, 10))
        #add subplot in the corner
        fig, ax1 = plt.subplots(figsize=(20, 10))
        ax2 = fig.add_axes([0.55, 0.66, 0.3, 0.2])
        ax1.set_title(gdir.rgi_id + ' flowline ' + str(i))
        box = ax1.get_position()
        ax1.set_position([box.x0, box.y0, box.width * 0.95, box.height])

        x = np.arange(
            y_2000.fls[i].nx) * y_2000.fls[i].dx * y_2000.fls[i].map_dx
        for j in range(len(result_list)):
            if result_list[j][0] != None:
                ax1.plot(
                    x,
                    result_list[j][0].fls[i].surface_h,
                    alpha=0.8,
                )
                ax2.plot(
                    x,
                    result_list[j][1].fls[i].surface_h,
                    alpha=0.8,
                )

        ax1.plot(x, y_1880.fls[i].surface_h, 'k:')
        ax2.plot(x, y_2000.fls[i].surface_h, 'k')

        ax1.plot(x, y_1880.fls[i].bed_h, 'k')
        ax2.plot(x, y_2000.fls[i].bed_h, 'k')

        plot_dir = os.path.join(cfg.PATHS['working_dir'], 'plots',
                                'Ben_idea_parallel_without_length')

        if not os.path.exists(plot_dir):
            os.makedirs(plot_dir)

        plt.savefig(
            os.path.join(plot_dir, gdir.rgi_id + '_fls' + str(i) + '.png'))
    pickle.dump(result_list,
                open(os.path.join(plot_dir, gdir.rgi_id + '.pkl'), 'wb'))
    solution = [y_1880, y_2000]
    pickle.dump(
        solution,
        open(os.path.join(plot_dir, gdir.rgi_id + '_solution.pkl'), 'wb'))
Esempio n. 15
0
def _find_inital_glacier(final_model,
                         firstguess_mb,
                         y0,
                         y1,
                         rtol=0.01,
                         atol=10,
                         max_ite=100,
                         init_bias=0.,
                         equi_rate=0.0005,
                         ref_area=None):
    """ Iterative search for a plausible starting time glacier"""

    # Objective
    if ref_area is None:
        ref_area = final_model.area_m2
    log.info(
        'iterative_initial_glacier_search '
        'in year %d. Ref area to catch: %.3f km2. '
        'Tolerance: %.2f %%', np.int64(y0), ref_area * 1e-6, rtol * 100)

    # are we trying to grow or to shrink the glacier?
    prev_model = copy.deepcopy(final_model)
    prev_fls = copy.deepcopy(prev_model.fls)
    prev_model.reset_y0(y0)
    prev_model.run_until(y1)
    prev_area = prev_model.area_m2

    # Just in case we already hit the correct starting state
    if np.allclose(prev_area, ref_area, atol=atol, rtol=rtol):
        model = copy.deepcopy(final_model)
        model.reset_y0(y0)
        log.info(
            'iterative_initial_glacier_search: inital '
            'starting glacier converges '
            'to itself with a final dif of %.2f %%',
            utils.rel_err(ref_area, prev_area) * 100)
        return 0, None, model

    if prev_area < ref_area:
        sign_mb = -1.
        log.info(
            'iterative_initial_glacier_search, ite: %d. '
            'Glacier would be too '
            'small of %.2f %%. Continue', 0,
            utils.rel_err(ref_area, prev_area) * 100)
    else:
        log.info(
            'iterative_initial_glacier_search, ite: %d. '
            'Glacier would be too '
            'big of %.2f %%. Continue', 0,
            utils.rel_err(ref_area, prev_area) * 100)
        sign_mb = 1.

    # Log prefix
    logtxt = 'iterative_initial_glacier_search'

    # Loop until 100 iterations
    c = 0
    bias_step = 0.1
    mb_bias = init_bias - bias_step
    reduce_step = 0.01

    mb = copy.deepcopy(firstguess_mb)
    mb.temp_bias = sign_mb * mb_bias
    grow_model = FluxBasedModel(copy.deepcopy(final_model.fls),
                                mb_model=mb,
                                fs=final_model.fs,
                                glen_a=final_model.glen_a,
                                min_dt=final_model.min_dt,
                                max_dt=final_model.max_dt)
    while True and (c < max_ite):
        c += 1

        # Grow
        mb_bias += bias_step
        mb.temp_bias = sign_mb * mb_bias
        log.info(logtxt + ', ite: %d. New bias: %.2f', c, sign_mb * mb_bias)
        grow_model.reset_flowlines(copy.deepcopy(prev_fls))
        grow_model.reset_y0(0.)
        grow_model.run_until_equilibrium(rate=equi_rate)
        log.info(
            logtxt + ', ite: %d. Grew to equilibrium for %d years, '
            'new area: %.3f km2', c, grow_model.yr, grow_model.area_km2)

        # Shrink
        new_fls = copy.deepcopy(grow_model.fls)
        new_model = copy.deepcopy(final_model)
        new_model.reset_flowlines(copy.deepcopy(new_fls))
        new_model.reset_y0(y0)
        new_model.run_until(y1)
        new_area = new_model.area_m2

        # Maybe we done?
        if np.allclose(new_area, ref_area, atol=atol, rtol=rtol):
            new_model.reset_flowlines(new_fls)
            new_model.reset_y0(y0)
            log.info(
                logtxt + ', ite: %d. Converged with a '
                'final dif of %.2f %%', c,
                utils.rel_err(ref_area, new_area) * 100)
            return c, mb_bias, new_model

        # See if we did a step to far or if we have to continue growing
        do_cont_1 = (sign_mb < 0.) and (new_area < ref_area)
        do_cont_2 = (sign_mb > 0.) and (new_area > ref_area)
        if do_cont_1 or do_cont_2:
            # Reset the previous state and continue
            prev_fls = new_fls

            log.info(logtxt + ', ite: %d. Dif of %.2f %%. '
                     'Continue', c,
                     utils.rel_err(ref_area, new_area) * 100)
            continue

        # Ok. We went too far. Reduce the bias step but keep previous state
        mb_bias -= bias_step
        bias_step /= reduce_step
        log.info(logtxt + ', ite: %d. Went too far.', c)
        if bias_step < 0.1:
            break

    raise RuntimeError('Did not converge after {} iterations'.format(c))
def create_spinup_glacier(gdir, rgi_id_to_name, yr_start_run, yr_end_run,
                          yr_spinup, used_mb_models):
    """TODO
    """
    # now creat spinup glacier with consensus flowline starting from ice free,
    # try to match length at rgi_date for 'realistic' experiment setting
    fl_consensus = gdir.read_pickle('model_flowlines',
                                    filesuffix='_consensus')[0]
    length_m_ref = fl_consensus.length_m

    fls_spinup = copy.deepcopy([fl_consensus])
    fls_spinup[0].thick = np.zeros(len(fls_spinup[0].thick))
    halfsize = (yr_start_run - yr_spinup) / 2
    yr_rgi = gdir.rgi_date

    mb_spinup = MultipleFlowlineMassBalance(gdir,
                                            fls=fls_spinup,
                                            mb_model_class=ConstantMassBalance,
                                            filename='climate_historical',
                                            input_filesuffix='',
                                            y0=yr_spinup + halfsize,
                                            halfsize=halfsize)

    mb_historical = MultipleFlowlineMassBalance(gdir,
                                                fls=fls_spinup,
                                                mb_model_class=PastMassBalance,
                                                filename='climate_historical',
                                                input_filesuffix='')

    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

    glacier_name = rgi_id_to_name[gdir.rgi_id]
    if experiment_glaciers[glacier_name]['t_bias_spinup_limits'] is None:
        print(
            'returned spinup_run function for searching for the t_bias_limits!'
        )
        return gdir, spinup_run
    else:
        t_bias_spinup_limits = \
            experiment_glaciers[glacier_name]['t_bias_spinup_limits']

    if experiment_glaciers[glacier_name]['t_bias_spinup'] is None:
        # search for it by giving back
        t_bias_spinup = brentq(spinup_run,
                               t_bias_spinup_limits[0],
                               t_bias_spinup_limits[1],
                               maxiter=20,
                               disp=False)
    else:
        t_bias_spinup = experiment_glaciers[glacier_name]['t_bias_spinup']

    print(
        f'{gdir.name} spinup tbias: {t_bias_spinup} with L mismatch at rgi_date:'
        f' {spinup_run(t_bias_spinup)} m')

    mb_spinup.temp_bias = t_bias_spinup
    model_spinup = FluxBasedModel(copy.deepcopy(fls_spinup), mb_spinup, y0=0)
    model_spinup.run_until_equilibrium(max_ite=1000)

    gdir.write_pickle(model_spinup.fls,
                      'model_flowlines',
                      filesuffix='_spinup')
def find_initial_state(gdir):

    global past_climate
    global y_1900, y_1850
    global y_start
    global x
    global ax1, ax2, ax3

    fls = gdir.read_pickle('model_flowlines')
    past_climate = PastMassBalance(gdir)
    random_climate = RandomMassBalance(gdir)
    commit_model = FluxBasedModel(fls,
                                  mb_model=random_climate,
                                  glen_a=cfg.A,
                                  y0=1850)
    commit_model.run_until_equilibrium()
    y_1850 = copy.deepcopy(commit_model)
    commit_model = FluxBasedModel(commit_model.fls,
                                  mb_model=past_climate,
                                  glen_a=cfg.A,
                                  y0=1850)

    commit_model.run_until(2000)
    y_1900 = copy.deepcopy(commit_model)
    x = np.arange(
        y_1900.fls[-1].nx) * y_1900.fls[-1].dx * y_1900.fls[-1].map_dx

    plt.figure(figsize=(20, 10))
    fig, ax1 = plt.subplots()
    ax2 = fig.add_axes([0.55, 0.66, 0.3, 0.2])
    ax1.set_title(gdir.rgi_id)

    box = ax1.get_position()
    ax1.set_position([box.x0, box.y0, box.width * 0.95, box.height])

    # Put a legend to the right of the current axis

    #plt.setp(ax1.get_xticklabels(), visible=False)
    #plt.plot(x, y_1850.fls[-1].surface_h, 'k:', label='solution')
    #plt.plot(x, y_1850.fls[-1].bed_h, 'k', label='bed')
    #plt.legend(loc='best')

    #ax2 = plt.subplot(412, sharex=ax1)
    #plt.setp(ax2.get_xticklabels(), visible=False)
    '''
    ax3 = plt.subplot(413,sharex=ax1)
    ax3.plot(x, np.zeros(len(x)), 'k--')

    ax4 = plt.subplot(414, sharex=ax1)
    ax4.plot(x, np.zeros(len(x)), 'k--')
    '''

    growing_model = FluxBasedModel(fls,
                                   mb_model=past_climate,
                                   glen_a=cfg.A,
                                   y0=1850)

    y_start = copy.deepcopy(growing_model)

    colors = [
        pylab.cm.Blues(np.linspace(0.3, 1, 2)),
        pylab.cm.Reds(np.linspace(0.3, 1, 2)),
        pylab.cm.Greens(np.linspace(0.3, 1, 2))
    ]

    #for i in [0,0.2,0.4,0.6,0.8,1,5,10,15,20,25,30,35,40,45,50]:
    j = 0

    for i in [1]:
        k = 0
        col = colors[j]
        j = j + 1
        for t in [20, 40, 60, 80, 100, 120, 140, 150]:
            res = minimize(objfunc, [0],
                           args=(
                               gdir,
                               y_1900.fls,
                               t,
                               i,
                           ),
                           method='COBYLA',
                           tol=1e-04,
                           options={
                               'maxiter': 500,
                               'rhobeg': 2
                           })
            try:
                result_model_1850, result_model_1900 = run_model(
                    res.x, gdir, y_1900.fls, t, i)

                f = np.sum(abs(result_model_1900.fls[-1].surface_h-y_1900.fls[-1].surface_h) ** 2) + \
                    np.sum(abs(y_1900.fls[-1].widths - result_model_1900.fls[-1].widths) ** 2)

                dif_s = result_model_1900.fls[-1].surface_h - y_1900.fls[
                    -1].surface_h
                dif_w = result_model_1900.fls[-1].widths - y_1900.fls[-1].widths
                #if np.max(dif_s)<40 and np.max(dif_w)<15:
                ax1.plot(x,
                         result_model_1850.fls[-1].surface_h,
                         alpha=0.8,
                         color=col[k],
                         label='t=' + str(t))
                ax2.plot(x,
                         result_model_1900.fls[-1].surface_h,
                         alpha=0.8,
                         color=col[k])

            except:
                pass
            k = k + 1

    ax1.plot(x, y_1850.fls[-1].surface_h,
             'k:')  #, label='surface elevation (not known)')
    ax1.plot(x, y_1850.fls[-1].bed_h, 'k')  #, label='bed topography')
    ax2.plot(x,
             y_1900.fls[-1].surface_h,
             'k',
             label='surface elevation (observed)')
    ax2.plot(x, y_1900.fls[-1].bed_h, 'k', label='bed')
    #ax3.plot(x,np.zeros(len(x)),'k:')
    ax1.annotate('t = 1850',
                 xy=(0.1, 0.95),
                 xycoords='axes fraction',
                 fontsize=13)
    ax2.annotate('t = 2000',
                 xy=(0.1, 0.9),
                 xycoords='axes fraction',
                 fontsize=9)
    ax1.set_xlabel('Distance along the Flowline (m)')
    ax1.set_ylabel('Altitude (m)')

    ax2.set_xlabel('Distance along the Flowline (m)')
    ax2.set_ylabel('Altitude (m)')

    ax1.legend(loc='center left', bbox_to_anchor=(1, 0.5))
    ax2.legend(loc='best')
    plot_dir = os.path.join(cfg.PATHS['working_dir'], 'plots')
    if not os.path.exists(plot_dir):
        os.makedirs(plot_dir)
    plt.savefig(os.path.join(plot_dir, gdir.rgi_id + '.png'))
    plt.show()