예제 #1
0
    def setUp(self):
        x, t = symbols('x t')
        B = Matrix(1, 1, [-1])
        u = Matrix(1, 1, [1])
        state_vector = Matrix(1, 1, [x])
        srm = SmoothReservoirModel.from_B_u(state_vector, t, B, u)
        parameter_dict = {}
        start_values = np.array([1])
        times = np.arange(0, 6, 1)

        smr = SmoothModelRun(srm, parameter_dict, start_values, times)

        self.alpha = 1
        start_values_14C = start_values * self.alpha
        decay_rate = 1.0

        def Fa_func(t):
            return self.alpha

        self.smr_14C = SmoothModelRun_14C(smr, start_values_14C, Fa_func,
                                          decay_rate)

        dmr_from_pwc = DMR.from_SmoothModelRun(smr)
        fake_net_Us = DMR.from_SmoothModelRun(self.smr_14C).net_Us

        # we cannot infer net_Us_14C coming from data, hence we use the
        # net_Us from the 14C model coming from the Smooth 14C model
        # this is of no use in pracitical situations tough since once
        # we have smr, we can use smr_14C immediately instead of going
        # through DMRs
        self.dmr_from_pwc_14C = DiscreteModelRun_14C(dmr_from_pwc,
                                                     start_values_14C,
                                                     fake_net_Us, decay_rate)
예제 #2
0
def compute_Bs_discrete(single_site_dict, time_step_in_days):
    mdo = _load_mdo(single_site_dict, time_step_in_days, check_units=False)

    out = mdo.load_xs_Us_Fs_Rs()
    xs, Us, Fs, Rs = out
    times = mdo.time_agg.data.filled()
    nr_pools = mdo.model_structure.nr_pools

    data = np.nan * np.ones((len(times), nr_pools, nr_pools))

    try:
        Bs = DMR.reconstruct_Bs(
            xs.data.filled(),
            Fs.data.filled(),
            Rs.data.filled()
        )
            
        data[:-1, ...] = Bs
    except (DMRError, ValueError, OverflowError) as e:
        error = str(e)
        print(error, flush=True)
        print(
            "lat", single_site_dict["lat"],
            "lon", single_site_dict["lon"],
            "prob", single_site_dict["prob"]
        )

    info = tuple()
    return data, info
예제 #3
0
def pool_age_density_val(
    x0_c: np.ndarray,
    times: np.ndarray,
    age_bin_indices: np.ndarray,  # integer
    B_c: np.ndarray,
    U_c: np.ndarray,
    start_age_densities_of_x0_and_a: Callable[[np.ndarray, float], np.ndarray],
):
    # Note that the chunksize is supposed to be one
    # We have only one startvector
    npools, _ = x0_c.shape
    it_max = len(times)
    print(it_max)
    x0 = x0_c[:, 0]  # .reshape(9)

    Bs = [B_c[i, :, :, 0] + np.eye(9) for i in range(it_max)]
    Us = [U_c[i, :, 0] for i in range(it_max)]
    dmr = DMR.from_Bs_and_net_Us(x0, times, Bs, Us)

    def start_age_densities(a):
        return start_age_densities_of_x0_and_a(x0, a)

    start_age_densities_of_bin_index = (
        hr.pool_wise_bin_densities_from_smooth_densities_and_index(
            start_age_densities, npools, dmr.dt))

    #
    res = np.zeros((len(age_bin_indices), len(times), npools, 1))

    p_dmr = dmr.pool_age_densities_func(start_age_densities_of_bin_index)
    pad = p_dmr(age_bin_indices)
    res[:, 1:, :, 0] = pad
    # sol=dmr.solve()[:-1,:].reshape(U_c.shape) #remove the last value
    # return sol
    return res
예제 #4
0
    def test_DiscreteModelRun_14CFromFakeData(self):
        dmr_from_smr_14C = DiscreteModelRun.from_SmoothModelRun(self.smr_14C)
        dmr_14C = DiscreteModelRun_14C(
            DiscreteModelRun.from_SmoothModelRun(self.smr),
            self.start_values_14C, dmr_from_smr_14C.net_Us, self.decay_rate)

        meths = [
            "solve", "acc_net_external_input_vector",
            "acc_net_external_output_vector", "acc_net_internal_flux_matrix"
        ]
        for meth in meths:
            with self.subTest():
                self.assertTrue(
                    np.allclose(
                        getattr(self.smr_14C, meth)(),
                        getattr(dmr_14C, meth)()))
    def test_start_value_format(self):
        # create ReservoirModel
        C_1, C_2, C_3 = symbols('C_1 C_2 C_3')
        state_vector = Matrix(3, 1, [C_1, C_2, C_3])
        t = symbols('t')
        B = Matrix([[-2, 0, 1], [2, -2, 0], [0, 2, -2]])
        u = Matrix(3, 1, [1, 0, 0])

        srm = SmoothReservoirModel.from_B_u(state_vector, t, B, u)

        # create ModelRun
        ss = (-B**(-1) * u)
        #        start_values = np.array(ss).astype(np.float64).reshape((3,))
        start_values = np.array(ss).astype(np.float64)
        times = np.linspace(1919, 2009, 901)
        parameter_dict = {}
        smr = SmoothModelRun(srm, parameter_dict, start_values, times)
        smr.initialize_state_transition_operator_cache(lru_maxsize=None)

        DMR.from_SmoothModelRun(smr)
예제 #6
0
def valid_trajectory(x0_c, times, B_c, U_c):
    # Note that the chunksize is supposed to be one
    # We have only one startvector
    it_max = len(times)
    x0 = x0_c[:, 0]  # .reshape(9)
    Bs = [B_c[i, :, :, 0] + np.eye(9) for i in range(it_max)]
    Us = [U_c[i, :, 0] for i in range(it_max)]
    #    dmr = DMR.from_Bs_and_net_Us(x0,times,Bs,Us)
    #    sol=dmr.solve()[:-1,:].reshape(U_c.shape) #remove the last value
    dmr = DMR.from_Bs_and_net_Us(x0, times, Bs[:-1], Us[:-1])  # Holger
    sol = dmr.solve().reshape(U_c.shape)  # Holger
    return sol
예제 #7
0
def aggregate_xs(xs, nr_days):
    # Note that the chunksize is supposed to be one
    # We have only one startvector
    print("###########")
    print(x0_c.shape, type(x0_c))
    print(times.shape)
    # print(ages.shape)
    print(B_c.shape)
    print(U_c.shape)
    it_max = len(times)
    print(it_max)
    x0 = x0_c[:, 0]  # .reshape(9)
    Bs = [B_c[i, :, :, 0] + np.eye(9) for i in range(it_max)]
    Us = [U_c[i, :, 0] for i in range(it_max)]
    #    dmr = DMR.from_Bs_and_net_Us(x0,times,Bs,Us)
    #    sol=dmr.solve()[:-1,:].reshape(U_c.shape) #remove the last value
    dmr = DMR.from_Bs_and_net_Us(x0, times, Bs[:-1], Us[:-1])  # Holger
    sol = dmr.solve().reshape(U_c.shape)  # Holger
    return sol
예제 #8
0
us_cont = sub_ds_cont["us"]
Bs_cont = sub_ds_cont["Bs"]

pwc_mr = PWCModelRunFD.from_Bs_and_us(symbols("t"),
                                      data_times,
                                      start_values_cont.values,
                                      Bs_cont[:-1],
                                      us_cont[:-1],
                                      state_variables=sub_ds_cont.pool.values)

# discrete mr
start_values_disc = sub_ds_disc["start_values"]
Us_disc = sub_ds_disc["Us"]
Bs_disc = sub_ds_disc["Bs"]

dmr = DMR.from_Bs_and_net_Us(start_values_disc.values, data_times,
                             Bs_disc[:-1].values, Us_disc[:-1].values)

# -

fig, ax = plt.subplots(figsize=(8, 8))
pwc_mr.model.plot_pools_and_fluxes(ax, legend=False)
_ = ax.set_title("CARDAMOM")

# compute the solution
#soln = pwc_mr.solve()
soln_cont = sub_ds_cont["solution"].values
soln_disc = sub_ds_disc["solution"].values

# +
fig, axes = plt.subplots(ncols=2, nrows=3, figsize=(18, 12))
예제 #9
0
us_y6 = sub_ds_y6["us"]
Bs_y6 = sub_ds_y6["Bs"]

pwc_mr_y6 = PWCModelRunFD.from_Bs_and_us(symbols("t"),
                                         data_times_y6,
                                         start_values_y6.values,
                                         Bs_y6[:-1],
                                         us_y6[:-1],
                                         state_variables=sub_ds_y6.pool.values)

# monthly, discrete
start_values_dmr = sub_ds_dmr["start_values"]
Us = sub_ds_dmr["Us"]
Bs_dmr = sub_ds_dmr["Bs"]

dmr = DMR.from_Bs_and_net_Us(start_values_dmr.values, data_times_m,
                             Bs_dmr[:-1].values, Us[:-1].values)
# -

fig, ax = plt.subplots(figsize=(8, 8))
pwc_mr_m.model.plot_pools_and_fluxes(ax, legend=False)
_ = ax.set_title("CARDAMOM")

# compute the solution
#soln = pwc_mr.solve()
soln_m = sub_ds_m["solution"].values
soln_y0 = sub_ds_y0["solution"].values
soln_y6 = sub_ds_y6["solution"].values
soln_dmr = sub_ds_dmr["solution"].values

# +
fig, axes = plt.subplots(ncols=2, nrows=3, figsize=(18, 12))
예제 #10
0
def compute_global_btt_quantile(ds,
                                name,
                                q,
                                nr_time_steps,
                                time_step_in_days,
                                nr_sites=None,
                                sto_cache_size=None):
    # load and adapt area and landfrac datases

    ds_area_lf = xr.open_dataset(data_path.joinpath("LSFRAC2.nc"))
    ds_area_lf_adapted = ds_area_lf.sel(lat=ds.lat, lon=ds.lon)
    ds_area_lf_adapted.area_sphere.attrs["units"] = "m^2"

    ds_area_lf_adapted.coords["lat"] = np.float64(
        ds_area_lf_adapted.coords["lat"])
    ds_area_lf_adapted.coords["lon"] = np.float64(
        ds_area_lf_adapted.coords["lon"])

    for var_name, var in ds_area_lf_adapted.data_vars.items():
        ds_area_lf_adapted[var_name].coords["lat"] = np.float64(
            var.coords["lat"])
        ds_area_lf_adapted[var_name].coords["lon"] = np.float64(
            var.coords["lon"])

    # collect all sites with useful data
    coords_linear = np.where(
        (~np.isnan(ds.start_values[:, :, 0])\
        & (ds.start_values[:, :, 0] != -np.inf))\
        & (~np.isnan(ds.Bs[:, :, 0, 0, 0]))\
    )

    coords_tuples = [(x, y) for x, y in zip(*coords_linear)]
    #    print(len(coords_tuples), "sites available")

    if nr_sites is None:
        nr_sites = len(coords_tuples)

    nr_times = len(ds.time)

    F_btt_svs = []

    weights = np.nan * np.ones((nr_sites, nr_times - 1))
    total_outflux_C = np.zeros(nr_times - 1)
    total_Ras = np.zeros(nr_times - 1)
    times = np.arange(len(ds.time)) * time_step_in_days

    if nr_sites is None:
        nr_sites = len(coords_tuples)

    def func_maker(dmr):
        F0 = dmr.fake_cumulative_start_age_masses(nr_time_steps)
        F_sv = dmr.cumulative_pool_age_masses_single_value(F0)
        rho = 1 - dmr.Bs.sum(1)
        F_btt_sv = lambda ai, ti: (rho[ti] * F_sv(ai, ti)).sum() + dmr.Ras[ti]

        return F_btt_sv

    for nr_coord, coords in enumerate(tqdm(coords_tuples[:nr_sites])):
        lat_idx, lon_idx = coords
        sub_ds = ds.isel(lat=lat_idx, lon=lon_idx)

        # load DMR
        start_values = sub_ds["start_values"].values
        Bs = sub_ds["Bs"].values
        Us = sub_ds["Us"].values
        Ras = sub_ds["Ras"].values

        dmr = DMR.from_Bs_and_net_Us(start_values, times, Bs[:nr_times - 1],
                                     Us[:nr_times - 1])
        Ras = Ras[:nr_times - 1]
        dmr.Ras = Ras

        # create cumulative BTT distribution single value
        F_btt_sv = func_maker(dmr)

        land_sub_ds = ds_area_lf_adapted.sel(lat=ds.lat[lat_idx],
                                             lon=ds.lon[lon_idx])
        weight = np.float(
            land_sub_ds.area_sphere * land_sub_ds.landfrac) / 1e12

        F_btt_svs.append(F_btt_sv)

        weights[nr_coord, :] = weight
        R = dmr.acc_net_external_output_vector()
        total_outflux_C += weight * R.sum(axis=1)
        total_Ras += weight * Ras

        # initialize a state transition operator cache for this dmr
        if sto_cache_size:
            dmr.initialize_state_transition_operator_matrix_cache(
                sto_cache_size)

    # the global quantile function is a weighted average of the local quantile functions
    # weights are the respective masses of outflux (area*landfrac*R.sum) in each time step
    @lru_cache()
    def F_btt_sv_global(ai, ti):
        res = np.sum(
            np.array([
                weight * F_btt_sv(int(ai), ti)
                for weight, F_btt_sv in zip(weights[:, ti], F_btt_svs)
            ]))
        return res

    global_btt_quantiles = np.nan * np.ones(nr_times, dtype=np.float64)

    quantile_ai = 0
    for ti in tqdm(range(len(times) - 1)):
        critical_value = q * (total_outflux_C[ti] + total_Ras[ti])
        quantile_ai = generalized_inverse_CDF(
            lambda ai: F_btt_sv_global(ai, ti), critical_value, x1=quantile_ai)

        if F_btt_sv_global(quantile_ai, ti) > critical_value:
            if quantile_ai > 0:
                quantile_ai = quantile_ai - 1

        # save result for timestep ti
        global_btt_quantiles[ti] = quantile_ai * time_step_in_days

    # prepare return dataset
    data_vars = dict()
    data_vars[name] = xr.DataArray(data=global_btt_quantiles, dims=["time"])

    res_ds = xr.Dataset(data_vars=data_vars, coords={"time": ds.time.data})
    #    sub_ds.close()

    return res_ds
    def test_from_SmoothModelRun(self):
        x_0, x_1, t, k, u = symbols("x_0 x_1 k t u")
        inputs = {0: u * (2 - 2 * sin(2 * t)), 1: u}
        outputs = {0: x_0 * k, 1: x_1**2 * k}
        internal_fluxes = {(0, 1): x_0, (1, 0): 0.5 * x_1}
        srm = SmoothReservoirModel([x_0, x_1], t, inputs, outputs,
                                   internal_fluxes)

        t_max = 2 * np.pi
        times = np.linspace(0, t_max, 21)
        times_fine = np.linspace(0, t_max, 81)
        x0 = np.float(10)
        start_values = np.array([x0, x0])
        parameter_dict = {k: 0.012, u: 10.7}

        smr = SmoothModelRun(srm, parameter_dict, start_values, times)
        smr_fine = SmoothModelRun(srm, parameter_dict, start_values,
                                  times_fine)

        xs, net_Us, net_Fs, net_Rs = smr.fake_net_discretized_output(times)
        xs, gross_Us, gross_Fs, gross_Rs \
            = smr.fake_gross_discretized_output(times)
        xs_fine, gross_Us_fine, gross_Fs_fine, gross_Rs_fine \
            = smr_fine.fake_gross_discretized_output(times_fine)

        dmr_from_pwc = DMR.from_SmoothModelRun(smr)
        dmr_from_fake_net_data = DMR.reconstruct_from_fluxes_and_solution(
            times, xs, net_Fs, net_Rs)
        dmr_from_fake_gross_data_ffas \
            = DMR.reconstruct_from_fluxes_and_solution(
                times,
                xs,
                gross_Fs,
                gross_Rs
            )
        dmr_from_fake_gross_data_ff = DMR.from_fluxes(start_values, times,
                                                      gross_Us, gross_Fs,
                                                      gross_Rs)
        dmr_from_fake_gross_data_ff_fine = DMR.from_fluxes(
            start_values, times_fine, gross_Us_fine, gross_Fs_fine,
            gross_Rs_fine)

        self.assertTrue(np.allclose(smr.solve(), dmr_from_pwc.solve()))

        self.assertTrue(
            np.allclose(smr.solve(), dmr_from_fake_net_data.solve()))

        # very unexpectedly the solution
        # can be reconstructed from the right start_value
        # the WRONG inputs WRONG internal fluxes and
        # WRONG outputs
        self.assertTrue(
            np.allclose(smr.solve(),
                        dmr_from_fake_gross_data_ff.solve(),
                        rtol=1e-3))

        # Here we also expect different results.
        # We again abuse the DiscreteModelRun class
        # but this time we give it the right solution
        # which will be reproduced
        self.assertTrue(
            np.allclose(smr.solve(), dmr_from_fake_gross_data_ffas.solve()))
        # but the net influxes will be wrong
        self.assertFalse(
            np.allclose(smr.acc_net_external_input_vector(),
                        dmr_from_fake_gross_data_ffas.net_Us))
        #        plot_attributes(
        #            [
        #                smr,
        #                dmr_from_fake_net_data,
        #                dmr_from_fake_gross_data_ff,
        #                dmr_from_fake_gross_data_ffas
        #            ],
        #            'plot.pdf'
        #        )
        plot_stocks_and_fluxes(
            [
                smr,
                # dmr_from_fake_net_data,
                # dmr_from_pwc,
                dmr_from_fake_gross_data_ff,
                dmr_from_fake_gross_data_ff_fine
            ],
            'stocks_and_fluxes.pdf')