def test_plot_two_pool_with_internal_flux(self):
        # get the components ready
        # - initial age distributions
        tss = 1
        x, y = 4, 4
        s = (x, y)
        age_dist_0 = TsTpMassField(2 * np.ones(s), tss)

        x1, y1 = 4, 4
        s1 = (x1, y1)
        age_dist_1 = TsTpMassField(2 * np.zeros(s1), tss)

        # the code has to initialize pool_0 regarding the size of pool_1
        initial_plains = CompatibleTsTpMassFieldsPerPool(
            [age_dist_0, age_dist_1])
        # - deathrate fields
        # internal
        idr = dict()
        idr[(0, 1)] = TsTpDeathRateField(
            np.zeros(s), tss
        )  #one connection to second pool (well mixed=no preference for any age)
        idr[(0, 1)][1, 1] = 0.5
        idr[(0, 1)][2, 2] = 0.5
        idr[(0, 1)][3, 3] = 0.5
        # external
        edr = dict()
        ei = dict()
        ei[0] = 3
        ts = TimeStep(0, initial_plains, idr, edr, ei)
        TimeStepPlotter(ts).plot_pdfs()
    def test_gains(self):
        tss = 0.1
        x, y = 3, 3
        s = (x, y)
        val = 1
        arr = np.zeros(s)
        arr[2, 2] = val
        f_0 = TsTpMassField(arr, tss)
        mult = 2
        f_1 = TsTpMassField(mult * arr, tss)
        # only pipes can contribute to a pool
        pipe_contents = TsTpMassFieldsPerPipe({(0, 1): f_0, (2, 1): f_1})
        computed_gains = pipe_contents.gains

        # only pool one gains
        receivers = computed_gains.keys()
        self.assertEqual(list(computed_gains.keys()), [1])

        # the result is one dimensional
        self.assertTrue(isinstance(computed_gains[1], TsMassField))

        # the length of the result has increased by one
        # representing our policy to pinpoint the moment when
        # material becomes older excatly between the moments of
        # leaving one pool and reaching the next
        # material  aging in the pipeline
        self.assertTrue(computed_gains[1].shape, f_0.shape + (1, ))

        ref = np.zeros(x + 1)
        # the contributions are added up correctly
        # and appear one step shifted in Ts
        ref[3] = val + mult * val
        self.assertTrue((computed_gains[1].arr == ref).all())
Beispiel #3
0
 def setUp(self):
     self.x, self.y = 6, 6
     self.s = (self.x, self.y)
     self.arr = np.zeros(self.s)
     self.arr[5, 5] = 10
     self.arr[5, 4] = 20
     self.tss = 0.1  ## the time step size
     self.spad = TsTpMassField(self.arr, self.tss)
 def setUp(self):
     self.tss = 0.1
     arr0 = np.zeros((3, 3))
     ref0 = arr0
     arr1 = np.zeros((3, 3))
     ref1 = arr1
     f0 = TsTpMassField(arr0, self.tss)
     f1 = TsTpMassField(arr1, self.tss)
     self.fields = CompatibleTsTpMassFieldsPerPool([f0, f1])
Beispiel #5
0
 def test_external_losses(self):
     computed_losses = self.fields.external_losses(
         self.external_death_rate_fields)
     ref = TsTpMassFieldsPerPool()
     ref[0] = TsTpMassField(self.loss_factor * self.age_dist_0.arr,
                            self.tss)
     ref[1] = TsTpMassField(self.loss_factor * self.age_dist_1.arr,
                            self.tss)
     for k, v in ref.items():
         f = computed_losses[k]
         self.assertTrue((v.arr == f.arr).all())
    def test_plot_three_pool(self):
        # get the components ready
        # - initial age distributions
        tss = 1
        x, y = 5, 4
        s = (x, y)
        age_dist_0 = TsTpMassField(np.zeros(s), tss)
        age_dist_0[3, 3] = 1
        age_dist_0[3, 2] = 2
        age_dist_0[2, 2] = 4

        x1, y1 = 5, 4
        s1 = (x1, y1)
        age_dist_1 = TsTpMassField(np.zeros(s1), tss)
        age_dist_1[3, 3] = 0.5
        age_dist_1[3, 2] = 0.5
        age_dist_1[1, 1] = 0.5

        x2, y2 = 5, 4
        s2 = (x2, y2)
        age_dist_2 = TsTpMassField(np.zeros(s2), tss)
        age_dist_2[3, 0] = 2
        age_dist_2[1, 0] = 4
        age_dist_2[0, 0] = 6
        # the code has to initialize pool_0 regarding the size of pool_1
        initial_plains = CompatibleTsTpMassFieldsPerPool(
            [age_dist_0, age_dist_1, age_dist_2])
        # - deathrate fields
        # internal
        idr = dict()
        idr[(0, 1)] = TsTpDeathRateField(
            1 / 8 * np.ones(s), tss
        )  #one connection to second pool (well mixed=no preference for any age)
        idr[(0, 2)] = TsTpDeathRateField(
            1 / 8 * np.ones(s), tss
        )  #one connection to second pool (well mixed=no preference for any age)
        # external
        edr = dict()
        edr[0] = TsTpDeathRateField(
            1 / 4 * np.ones(s),
            tss)  # well mixed outflux regardless of age from pool 1
        edr[1] = TsTpDeathRateField(1 / 8 * np.ones(s1),
                                    tss)  # also from pool 2
        # - external input numbers
        ei = dict()
        ei[0] = 3
        ei[1] = 4
        ts = TimeStep(0, initial_plains, idr, edr, ei)

        ts.plot_pdfs()
    def test_plot_single_pool_with_outflux(self):
        # get the components ready
        # - initial age distributions
        tss = 1
        x, y = 2, 2
        s = (x, y)
        age_dist_0 = TsTpMassField(3 * np.ones(s),
                                   tss)  #homogeneous age distribution

        # the output from pool_1 has a bigger age_span than pool_0 can encompass
        # the code has to initialize pool_0 regarding the size of pool_1
        initial_plains = CompatibleTsTpMassFieldsPerPool([age_dist_0])
        # no internal deathrate fields because there is no other pool
        # to transfer material to
        idr = dict()
        # external deathrate
        # to check the effect we only remove water that has been
        # of one particular age bin.
        edr = dict()
        edr[0] = TsTpDeathRateField(np.zeros(s), tss)
        edr[0][1, 1] = 0.5
        # - external input numbers
        ei = dict()
        ei[0] = 2
        ts = TimeStep(0, initial_plains, idr, edr, ei)

        TimeStepPlotter(ts).plot_pdfs()
        refarr = np.zeros((x + 1, y + 1))
        refarr[2, 2] = 0.5
Beispiel #8
0
 def test_plot_single_pool_with_outflux(self):
     # get the components ready
     # - initial age distributions
     tss=1
     x,y=5,4
     s=(x,y)
     age_dist_0=TsTpMassField(np.zeros(s),tss)
     age_dist_0[3,3]=1
     age_dist_0[3,2]=2
     age_dist_0[2,2]=3
     
     # the output from pool_1 has a bigger age_span than pool_0 can encompass
     # the code has to initialize pool_0 regarding the size of pool_1
     initial_plains=CompatibleTsTpMassFieldsPerPool([age_dist_0])
     # - deathrate fields
     idr=dict()
     # external
     edr=dict()
     edr[0]=TsTpDeathRateField(np.zeros(s),tss) 
     edr[0][3,2]=0.5
     edr[0][3,1]=0.4
     edr[0][3,0]=0.3
     # - external input numbers
     ei=dict()
     ei[0]=3
     tsp=TimeStepPlotter(TimeStep(0,initial_plains,idr,edr,ei))
     tsp.plot_pdfs()
    def test_init(self):
        tss = 0.1
        with self.assertRaises(Exception) as cm:
            #empty list
            initial_fields = CompatibleTsTpMassFieldsPerPool([])

        # check a one pool example
        age_dist_0 = TsTpMassField(np.zeros((4, 3)), tss)
        age_dist_0[2, 2] = 100
        initial_fields = CompatibleTsTpMassFieldsPerPool([age_dist_0])

        # check a one 3 pool example
        initial_fields = CompatibleTsTpMassFieldsPerPool([
            TsTpMassField(np.zeros((3, 3)), tss),
            TsTpMassField(np.zeros((2, 1)), tss),
            TsTpMassField(np.zeros((4, 2)), tss)
        ])
        self.assertEqual(len(initial_fields), 3)

        # check that all pools can now receive sytem ages up to 4*tss althoug they were smaller at the beginnign
        tss = 0.1
        initial_fields = CompatibleTsTpMassFieldsPerPool([
            TsTpMassField(np.zeros((3, 3)), tss),
            TsTpMassField(np.zeros((2, 1)), tss),
            TsTpMassField(np.zeros((4, 2)), tss)
        ])
        for field in initial_fields.values():
            self.assertTrue(field.number_of_Ts_entries == 4)
Beispiel #10
0
 def test_internal_losses(self):
     internal_death_rate_funcs = dict()
     internal_death_rate_funcs[(0, 1)] = self.func
     internal_death_rate_funcs[(1, 0)] = self.func
     fields = self.fields
     t = self.time
     internal_death_rate_fields = {
         pipe_key: f(fields[pipe_key[0]], t)
         for pipe_key, f in internal_death_rate_funcs.items()
     }
     #print(fields)
     computed_losses = fields.internal_losses(internal_death_rate_fields)
     ref = TsTpMassFieldsPerPipe()
     ref[(0, 1)] = TsTpMassField(self.loss_factor * self.age_dist_0.arr,
                                 self.tss)
     ref[(1, 0)] = TsTpMassField(self.loss_factor * self.age_dist_1.arr,
                                 self.tss)
     for key, v in ref.items():
         f = computed_losses[key]
         self.assertTrue((v.arr == f.arr).all())
Beispiel #11
0
    def setUp(self):
        self.tss = 0.1
        x, y = 3, 3
        s = (x, y)
        arr = np.zeros(s)
        arr[2, 2] = 2
        arr2 = 2 * arr
        #copy for references in the tests
        self.arr = arr
        self.arr2 = arr2
        self.age_dist_0 = TsTpMassField(arr, self.tss)
        self.age_dist_1 = TsTpMassField(arr2, self.tss)
        size_diff = 5
        age_dist_2 = TsTpMassField(np.zeros((x + size_diff, y + size_diff)),
                                   self.tss)
        self.fields = TsTpMassFieldsPerPool({
            0: self.age_dist_0,
            1: self.age_dist_1
        })
        self.time = 10
        self.loss_factor = 0.3

        def constant_well_mixed_death_rate(age_dist, t):
            # these functions must be able to define a TsTpDeathRateField eta
            # of the same size as the age distribution it gets
            # for all the system ages and pool ages present in age_dist it must
            # be able to compute the deathrate
            return (TsTpDeathRateField(
                self.loss_factor * np.ones(age_dist.arr.shape), age_dist.tss))

        self.func = constant_well_mixed_death_rate
        external_death_rate_funcs = dict()
        external_death_rate_funcs[0] = self.func
        external_death_rate_funcs[1] = self.func
        fields = self.fields
        t = self.time
        external_death_rate_fields = {
            pool_key: f(fields[pool_key], t)
            for pool_key, f in external_death_rate_funcs.items()
        }
        self.external_death_rate_fields = external_death_rate_fields
Beispiel #12
0
 def test_receive(self):
     x, y = 5, 2
     valf = 1
     field = TsTpMassField(np.zeros((x, y)), self.tss)
     # although not relevant for this test the shifted
     # field would not have entries in [0,:],and [:,0] therefor we choose
     field[1, 1] = valf
     # note that the gains method  has already shifted the TsMassField
     # by tss so that the gains are the same size as the (also shifted)
     # receiver in Ts direction
     gain = TsMassField(5 * np.zeros(x), self.tss)
     # Since the gains have also been collected from other pools
     # there system age is at least tss
     # size in Ts direction so gains[0] must stay 0
     valg = 2
     gain[1] = valg
     field.receive(gain)
     ref = np.zeros((x, y))
     ref[1, 1] = valf  #as before
     ref[1, 0] = valg  #gains incorporated with pool age  0
     self.assertTrue((field.arr == ref).all())
    def test_init(self):
        f_0 = TsTpMassField(np.zeros((3, 3)), 0.1)
        with self.assertRaises(Exception) as cm:
            TsTpMassFieldsPerPipe(
                {1: f_0})  #only tuples of integer are allowed as indices

        with self.assertRaises(Exception) as cm:
            TsTpMassFieldsPerPipe({1:
                                   2})  #only TsTpMassFields allowed as values

        with self.assertRaises(Exception) as cm:
            TsTpMassFieldsPerPipe({
                (1, 1): 2
            })  # sender and receiver have to be different
Beispiel #14
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
Beispiel #15
0
class TestTsTpMassField(unittest.TestCase):
    def setUp(self):
        self.x, self.y = 6, 6
        self.s = (self.x, self.y)
        self.arr = np.zeros(self.s)
        self.arr[5, 5] = 10
        self.arr[5, 4] = 20
        self.tss = 0.1  ## the time step size
        self.spad = TsTpMassField(self.arr, self.tss)

    def test_loss(self):
        eta_dist = TsTpDeathRateField(np.ones(self.s) * 0.5, self.tss)
        l = self.spad.loss(eta_dist)

        self.assertEqual(l[5, 5], 5)
        self.assertEqual(l[5, 4], 10)

    def test_sum_over_all_pool_ages(self):
        res = self.spad.sum_over_all_pool_ages()
        self.assertTrue(isinstance(res, TsMassField))
        ref = np.zeros(self.x)
        ref[5] = 30  #10+20
        self.assertTrue((res.arr == ref).all())

    def test_shift(self):
        spad = self.spad
        spad.shift()
        ref = np.zeros((self.x + 1, self.y + 1))
        ref[6, 6] = 10
        ref[6, 5] = 20
        #print("\n##########shift",spad.arr)
        self.assertTrue((spad.arr == ref).all())

    def test_resize(self):
        spad = self.spad
        spad.resize(10)
        ref = np.zeros((10, self.y))
        ref[5, 5] = 10
        ref[5, 4] = 20
        self.assertTrue((spad.arr == ref).all())

    def test_receive_external(self):
        spad = self.spad
        spad.receive_external(5)
        ref = np.zeros((self.x, self.y))
        ref[5, 5] = 10
        ref[5, 4] = 20
        ref[0, 0] = 5
        self.assertTrue((spad.arr == ref).all())

    def test_receive(self):
        x, y = 5, 2
        valf = 1
        field = TsTpMassField(np.zeros((x, y)), self.tss)
        # although not relevant for this test the shifted
        # field would not have entries in [0,:],and [:,0] therefor we choose
        field[1, 1] = valf
        # note that the gains method  has already shifted the TsMassField
        # by tss so that the gains are the same size as the (also shifted)
        # receiver in Ts direction
        gain = TsMassField(5 * np.zeros(x), self.tss)
        # Since the gains have also been collected from other pools
        # there system age is at least tss
        # size in Ts direction so gains[0] must stay 0
        valg = 2
        gain[1] = valg
        field.receive(gain)
        ref = np.zeros((x, y))
        ref[1, 1] = valf  #as before
        ref[1, 0] = valg  #gains incorporated with pool age  0
        self.assertTrue((field.arr == ref).all())
Beispiel #16
0
    def test_list_comprehension(self):
        ############################################################
        # get the components ready
        # - initial age distributions
        tss = 1
        x, y = 9, 9
        s = (x, y)
        age_dist_0 = TsTpMassField(np.zeros(s), tss)
        age_dist_0[2, 2] = 100

        x1, y1 = 4, 4
        s = (x1, y1)
        age_dist_1 = TsTpMassField(np.zeros(s), tss)
        age_dist_1[3, 3] = 100
        # the output from pool_1 has a bigger age_span than pool_0 can encompass
        # the code has to initialize pool_0 regarding the size of pool_1
        initial_plains = CompatibleTsTpMassFieldsPerPool(
            [age_dist_0, age_dist_1])

        ############################################################
        # - deathrate functions
        loss_factor = 0.1
        external_death_rate_funcs = dict()
        internal_death_rate_funcs = dict()

        def constant_well_mixed_death_rate(age_dist, t):
            # these functions must be able to define a field eta
            # of the same size as the age distribution it gets
            # for all the ages present in age_dist it must
            # be able to compute the deathrate
            return (TsTpDeathRateField(
                loss_factor * np.ones(age_dist.arr.shape), age_dist.tss))

        external_death_rate_funcs[0] = constant_well_mixed_death_rate
        external_death_rate_funcs[1] = constant_well_mixed_death_rate
        internal_death_rate_funcs[(0, 1)] = constant_well_mixed_death_rate

        # - input functions
        def zero_input(t):
            return (0)

        def const_input(t):
            return (5)

        external_input_funcs = dict()
        external_input_funcs[0] = const_input
        external_input_funcs[1] = zero_input

        drf = lambda t: 0.2
        ############################################################
        # initialize the Iterator
        it = TimeStepIterator(initial_plains,
                              external_input_funcs,
                              internal_death_rate_funcs,
                              external_death_rate_funcs,
                              t0=5,
                              number_of_steps=3)

        ############################################################
        ############################################################
        ############################################################
        # start testing
        # extract the complete information
        steps = [ts for ts in it]

        # or only the part one is interested in
        rectangles_for_first_pool = [ts.rectangles[0] for ts in it]
        #print("\n#####################################\nrectangles[0]",rectangles_for_first_pool)
        # or some parts
        tuples = [(ts.time, ts.rectangles[0].total_content) for ts in it]
        x = [t[0] for t in tuples]
        y = [t[1] for t in tuples]
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)
        ax.plot(x, y, "x")
        fig.savefig("plot.pdf")
        plt.close(fig.number)