예제 #1
0
def start_age_moments_from_empty_spinup(
    srm,
    t_max,
    parameter_dict,
    func_set,
    max_order
):
    times = np.linspace(0, t_max, 101)
    spin_up_mr = SmoothModelRun(
        srm,
        parameter_dict=parameter_dict,
        start_values=np.zeros(srm.nr_pools),
        times=times,
        func_set=func_set
    )
    m0 = start_age_moments_from_zero_initial_content(srm, max_order)

    moment_vector_list = [
        spin_up_mr.age_moment_vector(order, m0[0:order, :])[-1, :]
        for order in range(1, max_order+1)
    ]
    # stack the moment vectors line wise
    # first line first moment (columns are pools)
    # second line second moment (columns are pools)
    moment_arr = np.stack(moment_vector_list, 0)
    sol_t_max = spin_up_mr.solve()[-1, :]
    return moment_arr, sol_t_max
예제 #2
0
def panel_one(limited_srm,bm, par_dict_v1, control_start_values, times, func_dict):
    start_values=control_start_values[:-1]
    limited_smr = SmoothModelRun(limited_srm, par_dict_v1, start_values, times, func_dict)
    bmr=BastinModelRun( bm, par_dict_v1, control_start_values, times, func_dict)

    soln_uncontrolled = limited_smr.solve()

    soln_controlled = bmr.solve()
    fig=plt.figure(figsize=(10,10))
    #fig1.title('Total carbon'+title_suffs[version])
    ax1=fig.add_subplot(2,1,1)
    ax1.tick_params(axis='both', which='major', labelsize=12)
    ax1.plot(times, soln_uncontrolled[:,0],color='blue' ,label='Atmosphere')
    ax1.plot(times, soln_uncontrolled[:,1],color='green',label='Terrestrial Biosphere')
    ax1.plot(times, soln_uncontrolled[:,2],color='red'  ,label='Surface ocean')
    ax1.set_ylabel('Carbon stocks (Pg C)', fontsize=15)
    ax1.legend(loc=2)
    ax1.set_title("(a)")
    ax1.set_xlim(1900, 2500)

    ax2=fig.add_subplot(2,1,2)
    ax2.tick_params(axis='both', which='major', labelsize=12)
    ax2.plot(times, soln_controlled[:,0],color='blue' ,label='Atmosphere')
    ax2.plot(times, soln_controlled[:,1],color='green',label='Terrestrial Biosphere')
    ax2.plot(times, soln_controlled[:,2],color='red'  ,label='Surface ocean')
    ax2.set_ylabel('Carbon stocks (Pg C)', fontsize=15)
    ax2.set_xlabel('Time (yr)', fontsize=15)
    ax2.set_ylim(ax1.get_ylim())
    ax2.set_xlim(1900, 2500)
    ax2.set_title("(b)")
    
    #limited_soln_uncontrolled 
    fig.savefig(my_func_name()+'.pdf', bbox_inches='tight')
예제 #3
0
    def setUp(self):
        x, y, t = symbols("x y t")
        state_vector = Matrix([x, y])
        B = Matrix([[-1, 1.5], [0.5, -2]])
        u = Matrix(2, 1, [9, 1])
        srm = SmoothReservoirModel.from_B_u(state_vector, t, B, u)

        start_values = np.array([10, 40])
        self.start_values = start_values
        self.t_0 = 0
        self.t_max = 10
        self.ntmo = 10
        self.fac = 2
        self.times = np.linspace(self.t_0, self.t_max, self.ntmo + 1)

        self.smr = SmoothModelRun(srm, {}, start_values, self.times)

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

        def Fa_func(t):
            return alpha

        self.Fa_func = Fa_func

        self.smr_14C = SmoothModelRun_14C(self.smr, self.start_values_14C,
                                          self.Fa_func, self.decay_rate)
예제 #4
0
    def test_phi_cache_vals(self):
        k_0_val = 1
        k_1_val = 2
        x0_0 = np.float(0.5)
        x0_1 = np.float(1.5)

        x_0, x_1, k_0, k_1, t, u = symbols("x_0 x_1 k_0 k_1 t u")

        inputs = {0: u, 1: u * t}
        outputs = {0: k_0 * x_0**2, 1: k_1 * x_1}
        internal_fluxes = {}
        svec = Matrix([x_0, x_1])
        srm = SmoothReservoirModel(state_vector=svec,
                                   time_symbol=t,
                                   input_fluxes=inputs,
                                   output_fluxes=outputs,
                                   internal_fluxes=internal_fluxes)
        t_0 = 0
        t_max = 4
        nt = 2000  # the old way relies on the interpolation and goes wild for
        # small nt...
        times = np.linspace(t_0, t_max, nt)
        parameter_dict = {k_0: k_0_val, k_1: k_1_val, u: 1}
        func_dict = {}
        # make it a column vector for later use
        start_x = np.array([x0_0, x0_1])
        # create the model run
        smr = SmoothModelRun(model=srm,
                             parameter_dict=parameter_dict,
                             start_values=start_x,
                             times=times,
                             func_set=func_dict)
        nr_pools = srm.nr_pools
        #        smr.initialize_state_transition_operator_cache_2b(size=3)
        cache = smr._compute_state_transition_operator_cache(size=2)

        def baseVector(i):
            e_i = np.zeros((nr_pools, 1))
            e_i[i] = 1
            return e_i

        bvs = [baseVector(i) for i in range(nr_pools)]
        smrl = smr.linearize_old()
        for ind, phi in enumerate(cache.values):
            tmin = cache.keys[ind]
            tmax = cache.keys[ind + 1]
            for x in bvs:
                with self.subTest():
                    phi_x_old = smrl._state_transition_operator_for_linear_systems(
                        tmax, tmin, x)  # noqa: E501
                    phi_x_mat = np.matmul(phi, x).reshape(nr_pools, )
                    self.assertTrue(
                        np.allclose(phi_x_old, phi_x_mat, rtol=1e-2))
    def setUp(self):
        x, y, t, k = symbols("x y t k")
        u_1 = Function('u_1')(x, t)
        state_vector = Matrix([x, y])
        B = Matrix([[-1, 1.5], [k, -2]])
        u = Matrix(2, 1, [u_1, 1])
        self.srm = SmoothReservoirModel.from_B_u(state_vector, t, B, u)

        start_values = np.array([10, 40])
        t_0 = 0
        t_max = 10
        times = np.linspace(t_0, t_max, 11)
        disc_times = [5]

        parameter_dicts = [{k: 1}, {k: 0.5}]
        func_dicts = [{u_1: lambda x_14C, t: 9}, {u_1: lambda x_14C, t: 3}]

        pwc_mr = PWCModelRun(self.srm, parameter_dicts, start_values, times,
                             disc_times, func_dicts)

        self.alpha = 0.5
        start_values_14C = start_values * self.alpha

        def Fa_func(t):
            return self.alpha

        decay_rate = 1.0

        self.pwc_mr_14C = PWCModelRun_14C(pwc_mr, start_values_14C, Fa_func,
                                          decay_rate)

        timess = [
            np.linspace(t_0, disc_times[0], 6),
            np.linspace(disc_times[0], t_max, 6)
        ]

        smrs_14C = []
        tmp_start_values = start_values
        tmp_start_values_14C = start_values_14C
        for i in range(len(disc_times) + 1):
            smr = SmoothModelRun(self.srm,
                                 parameter_dict=parameter_dicts[i],
                                 start_values=tmp_start_values,
                                 times=timess[i],
                                 func_set=func_dicts[i])
            tmp_start_values = smr.solve()[-1]

            smrs_14C.append(
                SmoothModelRun_14C(smr, tmp_start_values_14C, Fa_func,
                                   decay_rate))
            tmp_start_values_14C = smrs_14C[i].solve()[-1]

        self.smrs_14C = smrs_14C
예제 #6
0
파일: mvars.py 프로젝트: chrislxj/bgc_md2
 def __init__(
     self, qpm, start_values_quant, times_quant,
 ):
     self.qpm = qpm
     p = qpm.parameterization
     if len(start_values_quant) != len(p.state_var_units):
         raise Exception('size inconsistency')
     times_num = np.array([to_number(tv, p.time_unit) for tv in times_quant])
     start_values_num = np.array(
         [to_number(sv, p.state_var_units[i]) for i, sv in enumerate(start_values_quant)]
     )
     self.smr = SmoothModelRun(
         qpm.srm, p.par_dict, start_values_num, times_num, p.func_dict
     )
    def setUp(self):
        C_1, C_2, k = symbols('C_1 C_2 k')
        B = Matrix([[-2, 0], [k, -2]])
        u = Matrix(2, 1, [1, 1])
        state_vector = Matrix(2, 1, [C_1, C_2])
        time_symbol = Symbol('t')

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

        parameter_dict = {k: 1}
        start_values = np.array([1.0 / 3.0, 4.0 / 9.0])
        times = np.linspace(0, 5, 6)
        smr = SmoothModelRun(srm, parameter_dict, start_values, times)
        #        smr.initialize_state_transition_operator_cache(lru_maxsize=None)

        self.alpha = 0.5
        #        self.alpha = ALPHA_14C
        start_values_14C = smr.start_values * self.alpha

        def Fa_func_14C(t):
            return self.alpha

        self.smr_14C = SmoothModelRun_14C(
            smr,
            start_values_14C,
            Fa_func_14C,
            1.0  # or use DECAY_RATE_14C_DAILY
        )
예제 #8
0
    def setUp(self):
        x, y, t = symbols("x y t")
        state_vector = Matrix([x, y])
        B = Matrix([[-1, 1.5], [0.5, -2]])
        u = Matrix(2, 1, [9, 1])
        srm = SmoothReservoirModel.from_B_u(state_vector, t, B, u)

        start_values = np.array([10, 40])
        self.start_values = start_values
        self.t_0 = 0
        self.t_max = 10
        self.ntmo = 10
        self.fac = 2
        self.times = np.linspace(self.t_0, self.t_max, self.ntmo + 1)

        self.smr = SmoothModelRun(srm, {}, start_values, self.times)
예제 #9
0
파일: mvars.py 프로젝트: MPIBGC-TEE/bgc_md2
class QuantityModelRun:
    def __init__(
        self,
        qpm,
        start_values_quant,
        times_quant,
    ):
        self.qpm = qpm
        p = qpm.parameterization
        if len(start_values_quant) != len(p.state_var_units):
            raise Exception('size inconsistency')
        times_num = np.array(
            [to_number(tv, p.time_unit) for tv in times_quant])
        start_values_num = np.array([
            to_number(sv, p.state_var_units[i])
            for i, sv in enumerate(start_values_quant)
        ])
        self.smr = SmoothModelRun(qpm.srm, p.par_dict, start_values_num,
                                  times_num, p.func_dict)

    def solve(self):
        # compute the solution with respect to the state_var_units given in
        # the model parameterization
        sol_num = self.smr.solve()

        # the result is correct since it comes with unit
        # and can be converted in any other unit.
        sol_quant = sol_num * self.qpm.parameterization.state_var_units

        return sol_quant
예제 #10
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)
예제 #11
0
def matrix_simul_from_symbolic(
        # for this model we also want the accumulated respiration
        pa,
        X0,
        npp_in,
        times):
    symbol_names = mvs.get_BibInfo().sym_dict.keys()
    for name in symbol_names:
        var(name)

    srm = mvs.get_SmoothReservoirModel()
    # we create a parameterdict for the fixed values
    # and extend it by the parameters provided
    parDict = {
        clay: 0.2028,
        silt: 0.2808,
        lig_wood: 0.4,
        f_wood2CWD: 1,
        f_metlit2mic: 0.45,
        NPP: npp_in
    }
    model_params = {Symbol(k): v for k, v in pa._asdict().items()}

    parDict.update(model_params)

    nsv1 = {Symbol(k): v for k, v in X0._asdict().items()}
    start_values = np.array([nsv1[k] for k in mvs.get_StateVariableTuple()])
    smr = SmoothModelRun(srm,
                         parameter_dict=parDict,
                         start_values=start_values,
                         times=times,
                         func_set={})
    sol = smr.solve()
    RESP_vec = smr.acc_gross_external_output_vector()
    RESP = np.sum(RESP_vec, axis=1)
    # in order to attach it to the solution we
    # have to have equal length. (in timesteps)
    # since the accumulated respiration vector
    # does not return the zeros for the t=0
    # but the solution contains the start values
    # we add the zero at the first time step
    RESP_w0 = np.concatenate([np.array([0]), RESP]).reshape(sol.shape[0], 1)
    # have to add zeros at the start (
    result = np.concatenate([sol, RESP_w0], axis=1)
    return result
    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)
예제 #13
0
    def test_net_vs_gross_for_different_time_steps(self):
        times_fine = np.linspace(self.t_0, self.t_max,
                                 self.fac * self.ntmo + 1)
        times_extra_fine = np.linspace(self.t_0, self.t_max,
                                       self.fac**2 * self.ntmo + 1)
        smr = self.smr

        smr_fine = SmoothModelRun(smr.model, smr.parameter_dict,
                                  smr.start_values, times_fine, smr.func_set)
        smr_extra_fine = SmoothModelRun(smr.model, smr.parameter_dict,
                                        smr.start_values, times_extra_fine,
                                        smr.func_set)
        # We build a discrete model where we use the gross fluxes
        # as arguments for BOTH (net and gross) fluxes.
        # This simulates the real world scenario.
        # Since the net fluxes are different from the gross fluxes
        # the discrete model assumes wrong net fluxes.
        # The correct values would be given by smr_fine.
        # For a smaller step size the gross fluxes would be essentially
        # the same (interpolating original ones) but the difference
        # to the net fluxes would be smaller, since the latter approach
        # the gross fluxes in the limit of small time steps.
        # So the bigger the time step the bigger the error in the
        # net fluxes and hence the reconstruction of the discrete Bs.
        xs_fine, net_Us_fine, net_Fs_fine, net_Rs_fine \
            = self.smr.fake_net_discretized_output(times_fine)
        xs_fine, gross_Us_fine, gross_Fs_fine, gross_Rs_fine \
            = self.smr.fake_gross_discretized_output(times_fine)
        dmr_wrong_fine = DMRWGF.reconstruct_from_fluxes_and_solution(
            times_fine,
            xs_fine,
            #           net_Us=gross_Us_fine,
            net_Fs=gross_Fs_fine,
            net_Rs=gross_Rs_fine,
            gross_Us=gross_Us_fine,
            gross_Fs=gross_Fs_fine,
            gross_Rs=gross_Rs_fine)
        plot_stocks_and_fluxes(
            [self.smr, smr_fine, smr_extra_fine, dmr_wrong_fine],
            'stocks_and_fluxes.pdf',
            labels=['mr_normal', 'mr_fine', 'mr_extra_fine', 'dmr_wrong_fine'])
예제 #14
0
def numeric_model_run_1(
    npsrm: NumericParameterizedSmoothReservoirModel,
    start_values_num: NumericStartValueArray,
    times_num: NumericSimulationTimes,
) -> SmoothModelRun:
    return SmoothModelRun(
        npsrm.srm,
        npsrm.parameterization.par_dict,
        start_values_num,
        times_num,
        npsrm.parameterization.func_dict,
    )
예제 #15
0
    def test_state_transition_operator_1d(self):
        # one-dimensional case
        C = Symbol('C')
        state_vector = [C]
        time_symbol = Symbol('t')
        # are inputs really ignored in the computation of Phi?
        input_fluxes = {0: 1}
        output_fluxes = {0: C}
        internal_fluxes = {}
        srm = SmoothReservoirModel(state_vector, time_symbol, input_fluxes,
                                   output_fluxes, internal_fluxes)

        start_values = np.array([5])
        times = np.linspace(0, 1, 11)
        smr = SmoothModelRun(srm, {}, start_values, times)

        x = np.array([1])

        Phix = smr._state_transition_operator(1, 0, x)

        self.assertEqual(Phix.shape, (1, ))
        self.assertTrue(abs(Phix - np.exp(-1)) < 1e-03)
    def setUp(self):
        x, y, t, k = symbols("x y t k")
        u_1 = Function('u_1')(x, t)
        state_vector = Matrix([x, y])
        B = Matrix([[-1,  1.5],
                    [k/(t+1), -2]])
        u = Matrix(2, 1, [u_1, 1])
        self.srm = SmoothReservoirModel.from_B_u(
            state_vector,
            t,
            B,
            u
        )

        start_values = np.array([10, 40])
        t_0 = 0
        t_max = 10
        times = np.linspace(t_0, t_max, 11)
        disc_times = [5]

        parameter_dicts = [{k: 1}, {k: 0.5*t}]
        func_dicts = [{u_1: lambda x, t: 9}, {u_1: lambda x, t: 3*t}]

        self.pwc_mr = PWCModelRun(
            self.srm,
            parameter_dicts,
            start_values,
            times,
            disc_times,
            func_dicts
        )

        timess = [
            np.linspace(t_0, disc_times[0], 6),
            np.linspace(disc_times[0], t_max, 6)
        ]

        smrs = []
        tmp_start_values = start_values
        for i in range(len(disc_times)+1):
            smrs.append(
                SmoothModelRun(
                    self.srm,
                    parameter_dict=parameter_dicts[i],
                    start_values=tmp_start_values,
                    times=timess[i],
                    func_set=func_dicts[i]
                )
            )
            tmp_start_values = smrs[i].solve()[-1]
        self.smrs = smrs
예제 #17
0
    def test_phi_2d_linear(self):
        C_0, C_1 = symbols('C_0 C_1')
        state_vector = [C_0, C_1]
        time_symbol = Symbol('t')
        input_fluxes = {}
        output_fluxes = {0: C_0, 1: C_1}
        internal_fluxes = {}
        srm = SmoothReservoirModel(state_vector, time_symbol, input_fluxes,
                                   output_fluxes, internal_fluxes)

        start_values = np.array([1, 2])
        t_0 = 0
        t_max = 4
        nt = 200
        times = np.linspace(t_0, t_max, nt)
        smr = SmoothModelRun(srm, {}, start_values, times)
        smr.initialize_state_transition_operator_cache(lru_maxsize=None,
                                                       size=2)

        nr_pools = srm.nr_pools

        def baseVector(i):
            e_i = np.zeros((nr_pools, 1))
            e_i[i] = 1
            return e_i

        bvs = [baseVector(i) for i in range(nr_pools)]

        for s in np.linspace(t_0, t_max, 5):
            for t in np.linspace(s, t_max, 5):

                phi_ref = np.eye(2) * np.exp(-(t - s))
                # test the matrix valued results
                with self.subTest():
                    self.assertTrue(
                        np.allclose(smr.Phi(t, s), phi_ref, rtol=1e-2))

                # test the vectored valued results
                for x in bvs:
                    for phi_x in [
                            smr._state_transition_operator(t, s, x),
                            smr._state_transition_operator_for_linear_systems(
                                t, s, x)
                    ]:
                        with self.subTest():
                            self.assertTrue(
                                np.allclose(phi_x,
                                            np.matmul(phi_ref,
                                                      x).reshape(nr_pools, ),
                                            rtol=1e-2))
    def setUp(self):
        x, y, t, k = symbols("x y t k")
        u_1 = Function('u_1')(x, t)
        state_vector = Matrix([x, y])
        B = Matrix([[-1, 1.5], [k / (t + 1), -2]])
        u = Matrix(2, 1, [u_1, 1])
        self.srm = SmoothReservoirModel.from_B_u(state_vector, t, B, u)

        start_values = np.array([10, 40])
        t_0 = 0
        t_max = 10
        times = np.linspace(t_0, t_max, 11)

        parameter_dict = {k: 1}
        func_dict = {u_1: lambda x, t: 9}

        self.smr = SmoothModelRun(self.srm, parameter_dict, start_values,
                                  times, func_dict)
예제 #19
0
    def test_state_transition_operator_2d(self):
        # two-dimensional case
        C_0, C_1 = symbols('C_0 C_1')
        state_vector = [C_0, C_1]
        time_symbol = Symbol('t')
        input_fluxes = {}
        output_fluxes = {0: C_0, 1: C_1}
        internal_fluxes = {}
        srm = SmoothReservoirModel(state_vector, time_symbol, input_fluxes,
                                   output_fluxes, internal_fluxes)

        start_values = np.array([5, 3])
        times = np.linspace(0, 1, 11)
        smr = SmoothModelRun(srm, {}, start_values, times)

        x = np.array([1, 3])
        Phix = smr._state_transition_operator(1, 0, x)

        self.assertEqual(Phix.shape, (2, ))

        # test t < t_0
        with self.assertRaises(Exception):
            Phix = smr._state_transition_operator(0, 1, x)

        # test if operator works correctly also late in time
        C = Symbol('C')
        state_vector = [C]
        time_symbol = Symbol('t')
        # are inputs really ignored in the computation of Phi?
        input_fluxes = {0: 1}
        output_fluxes = {0: C}
        internal_fluxes = {}
        srm = SmoothReservoirModel(state_vector, time_symbol, input_fluxes,
                                   output_fluxes, internal_fluxes)

        start_values = np.array([5])
        times = np.linspace(0, 100, 101)
        smr = SmoothModelRun(srm, {}, start_values, times)

        x = np.array([1])

        Phix = smr._state_transition_operator(91, 89, x)
        self.assertTrue(abs(Phix - np.exp(-2)) < 1e-03)
예제 #20
0
    def test_cache_hash(self):
        # test semi-symbolic semi-numerical SmoothReservoirModel
        C_0, C_1, C_2 = symbols('C_0 C_1 C_2')
        t = Symbol('t')

        u_0_expr = Function('u_0')(C_0, C_1, t)
        u_2_expr = Function('u_2')(t)

        X = Matrix([C_0, C_1, C_2])
        t_min, t_max = 0, 10
        u_data_0 = np.array([[t_min, 0.1], [t_max, 0.2]])
        u_data_2 = np.array([[t_min, 0.4], [t_max, 0.5]])
        symbolic_input_fluxes = {0: u_0_expr, 2: u_2_expr}

        u_0_interp = interp1d(u_data_0[:, 0], u_data_0[:, 1])

        def u0_func(C_0_val, C_1_val, t_val):
            return C_0_val * 0 + C_1_val * 0 + u_0_interp(t_val)

        u_1_interp = interp1d(u_data_2[:, 0], u_data_2[:, 1])

        def u2_func(t_val):
            return u_1_interp(t_val)

        func_set = {u_0_expr: u0_func, u_2_expr: u2_func}

        output_fluxes = {}
        internal_fluxes = {(0, 1): 5 * C_0, (1, 0): 4 * C_1**2}
        srm = SmoothReservoirModel(X, t, symbolic_input_fluxes, output_fluxes,
                                   internal_fluxes)

        start_values = np.array([1, 2, 3])
        times = np.linspace(t_min, t_max, 11)
        smr = SmoothModelRun(srm,
                             parameter_dict={},
                             start_values=start_values,
                             times=times,
                             func_set=func_set)

        smr.solve()
        # To be able to check if a stored state_transition_operator cache
        # is applicable to the SmoothModelRun object it is supposed to speed up
        smr.myhash()
예제 #21
0
#limited_srm_90 = SmoothReservoirModel(
#        state_vector, time_symbol, net_input_fluxes, net_output_fluxes,
#        lim_inf_90
#)
#half_saturation_bm_300=BastinModel(
#        limited_srm_300,half_saturation_utz_exp,z
#)
cubic_bm = BastinModel(limited_srm, cubic_utz_exp, z)
#deceleration_bm_300=BastinModel(
#        limited_srm_300,deceleration_utz_exp,z
#)

# create a dictionary of model runs
all_mrs = {
    "unlimited_smr":
    SmoothModelRun(unlimited_srm, par_dict, start_values, times, func_dict),
    "limited_smr":
    SmoothModelRun(limited_srm, par_dict, start_values, times, func_dict),
    #        "limited_90_smr":
    #            SmoothModelRun(
    #                limited_srm_90, par_dict, start_values , times, func_dict),
    #        "limited_300_controlled_half_saturation_10_20":
    #            BastinModelRun(
    #                half_saturation_bm_300, par_dict_half_saturation_10,
    #                start_values=np.array(list(start_values)+[20]),
    #                times=times, func_dict=func_dict),
    "limited_controlled_cubic_fast":
    BastinModelRun(cubic_bm,
                   par_dict_cubic_fast,
                   start_values=np.array(
                       list(start_values) + [par_dict_cubic_fast[z_max]]),
예제 #22
0
# + [markdown] hide_input=false hide_output=false run_control={"marked": false}
# We use the `SmoothReservoirModel`, the parameter dictionary, and the customly defined functions to create a `SmoothModelRun`. First for version 1, then for version 2. We also initialize a cache to dramatically speed up computations at almost no cost.

# + hide_input=false hide_output=false run_control={"marked": false}
# the system starts in equilibrium
start_values = np.array([A_eq, T_eq, S_eq])

# possibly nonlinear effects as a parameter dictionary
par_dict_v1 = {alpha: 0.2, beta: 10.0}  # nonlinear
par_dict_v2 = {alpha: 1.0, beta: 1.0}  # linear
par_dicts = [par_dict_v1, par_dict_v2]

# create the nonlinear model run and the according cache
smrs = []
for version in versions:
    smr = SmoothModelRun(srm, par_dicts[version], start_values, times,
                         func_set)
    smr.initialize_state_transition_operator_cache(lru_maxsize=5000, size=100)
    smrs.append(smr)
# -

# Now we plot the carbon stocks of the two model versions.

# + hide_input=false hide_output=false run_control={"marked": false}
for version in versions:
    soln = smrs[version].solve()

    # plot the solution
    plt.figure(figsize=(10, 7))
    plt.title('Total carbon' + title_suffs[version])

    plt.plot(times, soln[:, 0], color='blue', label='Atmosphere')
예제 #23
0
# # Create a numerical instance of the model
# We now use the set of parameter values described in the original publication, and define the initial conditions for the state variables, so we can run a forward simulation.
# We use here the class SmoothReservoirModel from the CompartmentalSystem package to load all the ingridients for the model and then be able to compute the solution.

# Replace symbolic model by numerical values
par_dict = {mu_b: 4.38, epsilon: 0.39, K_s: 53954.83, V_s: 59.13, F_NPP: 345.0}
start_values = np.array([11000, 50])
times = np.linspace(0, 100, 1000)

# Create smooth reservoir model (a class instance)
srm = SmoothReservoirModel.from_B_u(x, time_symbol, B, u)

# create the nonlinear model run (also a class instance, now from SmoothModelRun)
smrs = []
smr = SmoothModelRun(srm, par_dict, start_values, times)

soln = smr.solve()

# +
# plot the solution
plt.figure(figsize=(10, 7))
plt.title('Total carbon')

plt.plot(times, soln[:, 0], color='blue', label='C_s: carbon substrate')
plt.plot(times, soln[:, 1], color='green', label='C_b: microbial biomass')
#plt.plot(times, soln.sum(1), color =    'black', label = 'Total')

plt.legend(loc=2)
plt.xlabel('Time (yr)')
plt.ylabel('Mass (gC/m2)')
예제 #24
0
class TestModelRun(InDirTest):
    def setUp(self):
        x, y, t = symbols("x y t")
        state_vector = Matrix([x, y])
        B = Matrix([[-1, 1.5], [0.5, -2]])
        u = Matrix(2, 1, [9, 1])
        srm = SmoothReservoirModel.from_B_u(state_vector, t, B, u)

        start_values = np.array([10, 40])
        self.start_values = start_values
        self.t_0 = 0
        self.t_max = 10
        self.ntmo = 10
        self.fac = 2
        self.times = np.linspace(self.t_0, self.t_max, self.ntmo + 1)

        self.smr = SmoothModelRun(srm, {}, start_values, self.times)

#    @unittest.skip

    def test_DiscreteModelRunWithGrossFluxes_from_SmoothModelRun(self):
        dmr = DMRWGF.from_SmoothModelRun(self.smr)
        meths = [
            "solve", "acc_gross_external_input_vector",
            "acc_net_external_input_vector",
            "acc_gross_external_output_vector",
            "acc_net_external_output_vector", "acc_gross_internal_flux_matrix",
            "acc_net_internal_flux_matrix"
        ]
        for meth in meths:
            with self.subTest():
                self.assertTrue(
                    np.allclose(
                        getattr(self.smr, meth)(),
                        getattr(dmr, meth)()))

    def test_net_vs_gross_for_different_time_steps(self):
        times_fine = np.linspace(self.t_0, self.t_max,
                                 self.fac * self.ntmo + 1)
        times_extra_fine = np.linspace(self.t_0, self.t_max,
                                       self.fac**2 * self.ntmo + 1)
        smr = self.smr

        smr_fine = SmoothModelRun(smr.model, smr.parameter_dict,
                                  smr.start_values, times_fine, smr.func_set)
        smr_extra_fine = SmoothModelRun(smr.model, smr.parameter_dict,
                                        smr.start_values, times_extra_fine,
                                        smr.func_set)
        # We build a discrete model where we use the gross fluxes
        # as arguments for BOTH (net and gross) fluxes.
        # This simulates the real world scenario.
        # Since the net fluxes are different from the gross fluxes
        # the discrete model assumes wrong net fluxes.
        # The correct values would be given by smr_fine.
        # For a smaller step size the gross fluxes would be essentially
        # the same (interpolating original ones) but the difference
        # to the net fluxes would be smaller, since the latter approach
        # the gross fluxes in the limit of small time steps.
        # So the bigger the time step the bigger the error in the
        # net fluxes and hence the reconstruction of the discrete Bs.
        xs_fine, net_Us_fine, net_Fs_fine, net_Rs_fine \
            = self.smr.fake_net_discretized_output(times_fine)
        xs_fine, gross_Us_fine, gross_Fs_fine, gross_Rs_fine \
            = self.smr.fake_gross_discretized_output(times_fine)
        dmr_wrong_fine = DMRWGF.reconstruct_from_fluxes_and_solution(
            times_fine,
            xs_fine,
            #           net_Us=gross_Us_fine,
            net_Fs=gross_Fs_fine,
            net_Rs=gross_Rs_fine,
            gross_Us=gross_Us_fine,
            gross_Fs=gross_Fs_fine,
            gross_Rs=gross_Rs_fine)
        plot_stocks_and_fluxes(
            [self.smr, smr_fine, smr_extra_fine, dmr_wrong_fine],
            'stocks_and_fluxes.pdf',
            labels=['mr_normal', 'mr_fine', 'mr_extra_fine', 'dmr_wrong_fine'])

#    @unittest.skip

    def test_DiscreteModelRunFromFakeData(self):
        times = self.smr.times
        xs, net_Us, net_Fs, net_Rs \
            = self.smr.fake_net_discretized_output(times)
        xs, gross_Us, gross_Fs, gross_Rs \
            = self.smr.fake_gross_discretized_output(times)

        dmr = DMRWGF.reconstruct_from_fluxes_and_solution(
            times,
            xs,
            #           net_Us,
            net_Fs,
            net_Rs,
            gross_Us,
            gross_Fs,
            gross_Rs)
        meths = [
            "solve", "acc_gross_external_input_vector",
            "acc_net_external_input_vector",
            "acc_gross_external_output_vector",
            "acc_net_external_output_vector", "acc_gross_internal_flux_matrix",
            "acc_net_internal_flux_matrix"
        ]
        for meth in meths:
            with self.subTest():
                self.assertTrue(
                    np.allclose(
                        getattr(self.smr, meth)(),
                        getattr(dmr, meth)()))

#    @unittest.skip

    def test_PWCModelRunFD(self):
        times = self.smr.times
        xs, gross_Us, gross_Fs, gross_Rs \
            = self.smr.fake_gross_discretized_output(times)

        pwc_mr_fd = PWCModelRunFD.from_gross_fluxes(self.smr.model.time_symbol,
                                                    times,
                                                    self.smr.start_values,
                                                    gross_Us, gross_Fs,
                                                    gross_Rs)
        meths = [
            "solve", "acc_gross_external_input_vector",
            "acc_net_external_input_vector",
            "acc_gross_external_output_vector",
            "acc_net_external_output_vector", "acc_gross_internal_flux_matrix",
            "acc_net_internal_flux_matrix"
        ]
        for meth in meths:
            with self.subTest():
                ref = getattr(self.smr, meth)()
                res = getattr(pwc_mr_fd, meth)()
                self.assertTrue(
                    np.allclose(ref, res, rtol=3e-02)
                    # For this linear constant model
                    # the error should actually be zero
                    # and is only due to numerical inaccuracy.
                )
        plot_stocks_and_fluxes([self.smr, pwc_mr_fd], 'stocks_and_fluxes.pdf')
예제 #25
0
    def test_mean_age_distribution_for_BW(self):
        # create the model
        var("t, k_01,k_10,k_0o,k_1o")
        var("C_0,C_1")
        state_variables = [C_0, C_1]  # order is important
        inputs = {
            #0:sin(t)+2,#input to pool 0
            #1:cos(t)+2 #input to pool 1
            0: sympify(2),  #input to pool 0
            1: sympify(0)  #input to pool 1
        }
        outputs = {
            0: k_0o * C_0**3,  #output from pool 0
            1: k_1o * C_1**3  #output from pool 0
        }
        internal_fluxes = {
            (0, 1): k_01 * C_0 * C_1**2,  #flux from pool0  to pool 1
            (1, 0): k_10 * C_0 * C_1  #flux from pool1  to pool 0
        }
        time_symbol = t
        mod = SmoothReservoirModel(state_variables, time_symbol, inputs,
                                   outputs, internal_fluxes)

        #set the time step size
        tss = .1
        #create a Model run
        self.params = {k_01: 1 / 100, k_10: 1 / 100, k_0o: 1 / 2, k_1o: 1 / 2}

        start_values = [1, 2]
        times = np.arange(100) * tss  # time grid forward
        mr = SmoothModelRun(mod, self.params, start_values, times)

        # now create initial age distributions
        # since we start with system age 0 we start with very
        # small fields indeed
        # pool 0
        x, y = 1, 1
        s = (x, y)
        age_dist_0 = TsTpMassField(np.zeros(s), tss)
        age_dist_0[0, 0] = start_values[0]

        # pool 1
        x1, y1 = 1, 1
        s = (x1, y1)
        age_dist_1 = TsTpMassField(np.zeros(s), tss)
        age_dist_1[0, 0] = start_values[1]

        # initialize the combination (this would adjust for different system ages)
        initial_plains = CompatibleTsTpMassFieldsPerPool(
            [age_dist_0, age_dist_1])

        # we now build the deathrate functions
        # note that the factories depend
        # on the solution funtions

        # produce the output deathrate functions
        def external_death_rate_maker(sender, func, solfs):
            def wrapper(field, t):
                tss = field.tss
                loss = quad(func, t, t + tss)[0]
                stock = solfs[sender](t)
                relative_loss = loss / stock
                #print("stock:=",stock)
                #print("loss:=",loss)
                #print("ext_relative_loss:=",relative_loss)
                dr = TsTpDeathRateField(relative_loss * np.ones(field.shape),
                                        tss)
                return (dr)

            return (wrapper)

        external_death_rate_functions = dict()
        solfs = mr.sol_funcs()
        for sender, func in mr.output_flux_funcs().items():
            external_death_rate_functions[sender] = external_death_rate_maker(
                sender, func, solfs)

        # produce the internal deathrate functions
        def internal_death_rate_maker(key, func, solfs):
            def wrapper(field, t):
                sender = key[0]
                tss = field.tss
                loss = quad(func, t, t + tss)[0]
                stock = solfs[sender](t)
                relative_loss = loss / stock
                #print("int_relative_loss:=",relative_loss)
                dr = TsTpDeathRateField(relative_loss * np.ones(field.shape),
                                        tss)
                return (dr)

            return (wrapper)

        internal_death_rate_functions = dict()
        for key, func in mr.internal_flux_funcs().items():
            internal_death_rate_functions[key] = internal_death_rate_maker(
                key, func, solfs)

        # produce the external inputs
        def external_input_maker(receiver, func):
            def wrapper(t):
                return (quad(func, t, t + tss)[0])

            return (wrapper)

        external_inputs = dict()
        for receiver, func in mr.external_input_flux_funcs().items():
            external_inputs[receiver] = external_input_maker(receiver, func)

        start = times[0]
        age_dist_hist = TsTpMassFieldsPerPoolPerTimeStep.compute_from(
            initial_plains, external_inputs, internal_death_rate_functions,
            external_death_rate_functions, start,
            len(times) - 1)
        #age_dist_hist.single_pool_cartoon(0,"pool_0")
        fig = plt.figure()
        age_dist_hist.matrix_plot("plot_total_contents", fig)
        fig.savefig("total_content.pdf")  #
        fig = plt.figure()
        #age_dist_hist.matrix_plot3d("plot_system_age_distributions_with_bins",fig)
        age_dist_hist.matrix_plot3d(
            "plot_system_age_distributions_as_surfaces", fig)
        fig.savefig("system_age_distribution.pdf")
        fig = plt.figure()
        mr.plot_sols(fig)
        fig.savefig("mr_total_content.pdf")  #compare
예제 #26
0
    {}  # func dict
)

# define a dictionary to connect the symbols with the according functions
func_set = {xi: xi_func_numerical, G: u_func_numerical}

# the system starts in equilibrium
start_values = np.array([x_1e, x_2e, x_3e, x_4e, x_5e])
# start_values = np.zeros(5)

# parameter dictionary
par_dict = {G_eq: G_emanuel}

# create the nonlinear model run and the according cache
smrs = []
smr = SmoothModelRun(srm, par_dict, start_values, times, func_set)
smr.initialize_state_transition_operator_cache(lru_maxsize=5000, size=100)
smrs.append(smr)

soln = smr.solve()
cstocks = pd.DataFrame(soln, columns=pool_names)
stocks = cstocks.join(pd.DataFrame({"Time": times}))
stocks.to_csv("stocks.csv", index=False)

GPP = pd.DataFrame(smr.external_input_vector, columns=pool_names)
Re = pd.DataFrame(smr.external_output_vector, columns=pool_names)
GPP.to_csv("GPP.csv", index=False)
Re.to_csv("Re.csv", index=False)

##### load linear autonomous pool model in steady state #####
예제 #27
0
def test_stateTransitionOperator_by_different_methods():
    # The state transition operator Phi can be used to reproduce the solution
    k_0_val = 1
    k_1_val = 2
    x0_0 = np.float(0.5)
    x0_1 = np.float(1.5)
    delta_t = np.float(1. / 4.)
    #
    var(["x_0", "x_1", "k_0", "k_1", "t", "u"])
    #
    inputs = {0: u, 1: u * t}
    outputs = {0: k_0 * x_0**2, 1: k_1 * x_1}
    internal_fluxes = {}
    svec = Matrix([x_0, x_1])
    srm = SmoothReservoirModel(state_vector=svec,
                               time_symbol=t,
                               input_fluxes=inputs,
                               output_fluxes=outputs,
                               internal_fluxes=internal_fluxes)
    t_0 = 0
    t_max = 4
    nt = 5
    times = np.linspace(t_0, t_max, nt)
    double_times = np.linspace(t_0, t_max, 2 * (nt - 1) + 1)
    quad_times = np.linspace(t_0, t_max, 4 * (nt - 1) + 1)
    parameter_dict = {k_0: k_0_val, k_1: k_1_val, u: 1}
    func_dict = {}
    start_x = np.array([x0_0, x0_1])  #make it a column vector for later use
    #create the model run
    smr = SmoothModelRun(model=srm,
                         parameter_dict=parameter_dict,
                         start_values=start_x,
                         times=times,
                         func_set=func_dict)
    smr.build_state_transition_operator_cache(size=4)
    nr_pools = smr.nr_pools

    # to be able to compare the results we have to compute them for a
    # set of n linear independent vectors
    def baseVector(i):
        e_i = np.zeros((nr_pools, 1))
        e_i[i] = 1
        return e_i

    bvs = [baseVector(i) for i in range(nr_pools)]
    #pe('Phi_skew(2,1,bvs[0])',locals())
    #raise

    test_times = np.linspace(t_0, t_max, 11)

    # We now rebuild the solution by means of phi and plot it along with the original solution
    original_sol, sol_func = smr.solve()

    u_sym = srm.external_inputs
    u_num = numerical_function_from_expression(u_sym, (t, ), parameter_dict,
                                               {})

    def vectorlist2array(l):
        return np.stack([vec.flatten() for vec in l], 1)


#    def lists_dict2array_dict(d):
#        return {key:vectorlist2array(val) for key,val in d.items()}
#

    def continiuous_integral_values(integrator, times):
        start = time.time()
        res = vectorlist2array([
            integrator(
                lambda tau: smr._state_transition_operator(t, tau, u_num(tau)),
                t_0, t) for t in times
        ])
        stop = time.time()
        exec_time = stop - start
        #pe('exec_time',locals())
        return (times, res, exec_time)

    def discrete_integral_values(integrator, times):
        start = time.time()
        res = vectorlist2array([
            integrator(
                lambda tau: smr._state_transition_operator(t, tau, u_num(tau)),
                taus=+times[0:i + 1]) for i, t in enumerate(times)
        ])
        stop = time.time()
        exec_time = stop - start
        #pe('exec_time',locals())
        return (times, res, exec_time)

    ## reconstruct the solution with Phi and the integrand
    # x_t=Phi(t,t0)*x_0+int_t0^t Phi(tau,t0)*u(tau) dtau
    # x_t=a(t)+b(t)
    et = bvs[0] + bvs[1]
    phi_arrays = {
        'skew':
        (times,
         vectorlist2array([
             smr._state_transition_operator(t, t_0,
                                            et).reshape(srm.nr_pools, 1)
             for t in times
         ]))
    }

    a_arrays = {
        'skew':
        (times,
         vectorlist2array([
             smr._state_transition_operator(t, t_0,
                                            start_x).reshape(srm.nr_pools, 1)
             for t in times
         ])),
        'trapez1':
        (times,
         vectorlist2array([
             smr._state_transition_operator(t, t_0,
                                            start_x).reshape(srm.nr_pools, 1)
             for t in times
         ])),
        'trapez2':
        (double_times,
         vectorlist2array([
             smr._state_transition_operator(t, t_0,
                                            start_x).reshape(srm.nr_pools, 1)
             for t in double_times
         ])),
        'trapez4':
        (quad_times,
         vectorlist2array([
             smr._state_transition_operator(t, t_0,
                                            start_x).reshape(srm.nr_pools, 1)
             for t in quad_times
         ]))
    }
    nested_boundary_tuples = [(0, t) for t in reversed(times)]

    b_arrays_trapez = {}
    b_arrays = {
        'skew':
        continiuous_integral_values(array_integration_by_ode, times),
        'trapez1':
        discrete_integral_values(array_integration_by_values, times),
        'trapez2':
        discrete_integral_values(array_integration_by_values, double_times),
        'trapez4':
        discrete_integral_values(array_integration_by_values, quad_times)
    }

    b_arrays_quad = {
        'skew': continiuous_integral_values(array_quad_result, times)
    }

    x_arrays = {
        key: (a_arrays[key][0], a_arrays[key][1] + b_arrays[key][1])
        for key in a_arrays.keys()
    }
    #x_arrays['trapez']=(times,a_arrays['skew'][1]+b_arrays['trapez'][1])

    styleDict = OrderedDict({
        'skew': ('green', 6),
        'trapez1': ('black', 4),
        'trapez2': ('blue', 4),
        'trapez4': ('brown', 2)
    })

    def plot_comparison(axl, axr, d):
        for key in styleDict.keys():
            if key in d.keys():
                val = d[key]
                if len(val) == 3:
                    time = "{:7.1e}".format(val[2])
                else:
                    time = ""
                axl.plot(val[0],
                         val[1][0, :],
                         '+',
                         color=styleDict[key][0],
                         markersize=styleDict[key][1],
                         label=key + "[0]" + time)
                axr.plot(val[0],
                         val[1][1, :],
                         'x',
                         color=styleDict[key][0],
                         markersize=styleDict[key][1],
                         label=key + "[1]" + time)

    fig = plt.figure(figsize=(17, 27))
    rpn = 5
    cpn = 2
    r = 1
    axl = fig.add_subplot(rpn, cpn, r)
    plt.title("""phi components, nonlinear part of the system (x[0]) """)
    axr = fig.add_subplot(rpn, cpn, r + 1)
    plt.title("""phi components, linear part of the system (x[1]) """)
    plot_comparison(axl, axr, phi_arrays)
    axl.legend()

    r += cpn
    axl = fig.add_subplot(rpn, cpn, r)
    plt.title('''
    original solution and reconstruction via phi, 
    imprecise for trapez_rule and wrong for the old method
    ''')
    axr = fig.add_subplot(rpn, cpn, r + 1)
    axl.plot(times,
             original_sol[:, 0],
             'o',
             color='blue',
             label="original_sol[:,0]")
    axr.plot(times,
             original_sol[:, 1],
             'o',
             color='blue',
             label="original_sol[:,1]")

    plot_comparison(axl, axr, x_arrays)
    axl.legend()
    axr.legend()

    r += cpn
    axl = fig.add_subplot(rpn, cpn, r)
    plt.title('phi(t,ti-0) x0 ')
    axr = fig.add_subplot(rpn, cpn, r + 1)
    ax = fig.add_subplot(rpn, cpn, r)
    plot_comparison(axl, axr, a_arrays)
    axl.legend()
    axr.legend()

    r += cpn
    axl = fig.add_subplot(rpn, cpn, r)
    plt.title('\int_{t0}^t phi(tau,t) u(tau) d tau')
    axr = fig.add_subplot(rpn, cpn, r + 1)
    plot_comparison(axl, axr, b_arrays)
    axl.legend()
    axr.legend()

    #r+=cpn
    r += cpn
    axl = fig.add_subplot(rpn, cpn, r)
    plt.title('\int_{t0}^t phi(tau,t) u(tau) d tau by quad')
    axr = fig.add_subplot(rpn, cpn, r + 1)
    plot_comparison(axl, axr, b_arrays_quad)
    axl.legend()
    axr.legend()

    fig.savefig("solutions.pdf")
예제 #28
0
def start_age_distributions_from_empty_spinup(
    srm,
    t_max,
    parameter_dict,
    func_set
):
    """
    Finite age spin up from empty pools

    Creates a SmoothModelRun object with empty pools at :math:`t=0`,
    runs it until :math:`t=t_{max}` an returns the age distribution at
    :math:`t_{max}`

    Args:
        srm (SmoothReservoirModel) : The (symbolic) model
        t_max (float):
            The end of the spinup (which starts at t=0 and runs until t=t_max)

        parameter_dict (dict) :
            The parameter set that transforms the symbolic model into a
            numeric one.
            The keys are the sympy symbols, the values are the values used for
            the simulation.
        func_set (dict):
            The keys are the symbolic
            sympy expressions for external functions
            the values are the numeric functions to be used in the simulation
    Returns:
        (a_dist_at_end_of_spinup, sol_t_max)  (tuple):

        a_dist_at_end_of_spinup is a vector valued function of age.
        a_dist_at_end_of_spinup(a)[i] reflects the mass of age :math:`a`
        in pool i.

        sol_t_max is a one dimensional vector
        representing the pool contents at the end of the spinup.
        This is returned since it is very likely needed as start vector in the
        simulation for which the start distributions has been computed.
    """
    a_dist_at_start_of_spinup =\
        start_age_distributions_from_zero_initial_content(srm)
    # unfortunately the number of time steps has some influence on accuracy
    # although the ode solver guarantees a minimum it gets better if you
    # force it to make smaller steps...
#    times=[0,t_max]
    times = np.linspace(0, t_max, 101)
    spin_up_mr = SmoothModelRun(
        srm,
        parameter_dict=parameter_dict,
        start_values=np.zeros(srm.nr_pools),
        times=times,
        func_set=func_set
    )

    # p_sv(a,t) returns the mass of age a at time t
    p_sv = spin_up_mr.pool_age_densities_single_value(
        a_dist_at_start_of_spinup
    )
    sol_t_max = spin_up_mr.solve()[-1, :]

    def a_dist_at_end_of_spinup(age):
        return p_sv(age, t_max)

    return a_dist_at_end_of_spinup, sol_t_max
예제 #29
0
    def test_phi_2d_non_linear(self):
        k_0_val = 1
        k_1_val = 2
        x0_0 = np.float(0.5)
        x0_1 = np.float(1.5)
        x_0, x_1, k_0, k_1, t, u = symbols("x_0 x_1 k_0 k_1 t u")

        inputs = {0: u, 1: u * t}
        outputs = {0: k_0 * x_0**2, 1: k_1 * x_1}
        internal_fluxes = {}
        svec = Matrix([x_0, x_1])
        srm = SmoothReservoirModel(state_vector=svec,
                                   time_symbol=t,
                                   input_fluxes=inputs,
                                   output_fluxes=outputs,
                                   internal_fluxes=internal_fluxes)
        t_0 = 0
        t_max = 4
        nt = 20000
        times = np.linspace(t_0, t_max, nt)
        parameter_dict = {k_0: k_0_val, k_1: k_1_val, u: 1}
        func_dict = {}
        # make it a column vector for later use
        start_x = np.array([x0_0, x0_1])
        # create the model run
        smr = SmoothModelRun(
            model=srm,
            parameter_dict=parameter_dict,
            start_values=start_x,
            times=times,
            func_set=func_dict,
        )
        smr.initialize_state_transition_operator_cache(lru_maxsize=None,
                                                       size=4)

        nr_pools = srm.nr_pools

        def baseVector(i):
            e_i = np.zeros((nr_pools, 1))
            e_i[i] = 1
            return e_i

        bvs = [baseVector(i) for i in range(nr_pools)]

        smrl = smr.linearize_old()

        for s in np.linspace(t_0, t_max, 5):
            for t in np.linspace(s, t_max, 5):
                for x in bvs:
                    with self.subTest():
                        self.assertTrue(
                            np.allclose(
                                smr._state_transition_operator(t, s, x),
                                smrl.
                                _state_transition_operator_for_linear_systems(
                                    t, s, x),  # noqa: E501
                                rtol=1.5 * 1e-2))

        for t in np.linspace(t_0, t_max, 6):
            for phi_mat in [smr.Phi(t, t_0), smrl.Phi(t, t_0)]:
                for x in bvs:
                    with self.subTest():
                        self.assertTrue(
                            np.allclose(np.matmul(phi_mat,
                                                  x).reshape(nr_pools, ),
                                        smr._state_transition_operator(
                                            t, t_0, x),
                                        rtol=1.5 * 1e-2))
예제 #30
0
    def test_save_and_load_state_transition_operator_cache(self):
        # two-dimensional
        C_0, C_1 = symbols('C_0 C_1')
        state_vector = Matrix([C_0, C_1])
        time_symbol = Symbol('t')
        input_fluxes = {0: 1, 1: 2}
        output_fluxes = {0: C_0, 1: C_1}
        internal_fluxes = {}
        srm = SmoothReservoirModel(state_vector, time_symbol, input_fluxes,
                                   output_fluxes, internal_fluxes)

        start_values = np.array([5, 3])
        times = np.linspace(0, 1, 6)

        smr = SmoothModelRun(srm, {}, start_values, times)

        #        ages = np.linspace(-1,1,3)
        # negative ages will be cut off automatically
        #        start_age_densities = lambda a: np.exp(-a)*start_values
        smr.initialize_state_transition_operator_cache(lru_maxsize=None,
                                                       size=100)

        ca = smr._state_transition_operator_cache

        filename = 'sto.cache'
        smr.save_state_transition_operator_cache(filename)
        smr.load_state_transition_operator_cache(filename)

        self.assertTrue(np.all(ca == smr._state_transition_operator_cache))

        # now we change the model run and make sure that the
        # saved cache is recognized as invalid.
        start_values_2 = np.array([6, 3])
        smr = SmoothModelRun(srm, {}, start_values_2, times)
        with self.assertRaises(Exception):
            smr.load_state_transition_operator_cache(filename)