Example #1
0
    def test_agg_anyall(self, simple_linear_model):
        """Test the "any" and "all" aggregation functions"""
        model = simple_linear_model
        model.timestepper.delta = 1
        model.timestepper.start = "2017-01-01"
        model.timestepper.end = "2017-01-03"

        scenarioA = Scenario(model, "Scenario A", size=2)
        scenarioB = Scenario(model, "Scenario B", size=5)
        num_comb = len(model.scenarios.get_combinations())

        parameters = {
            0: DummyIndexParameter(model, 0, name="p0"),
            1: DummyIndexParameter(model, 1, name="p1"),
            2: DummyIndexParameter(model, 2, name="p2"),
        }

        data = [(0, 0), (1, 0), (0, 1), (1, 1), (1, 1, 1), (0, 2)]
        data_parameters = [[parameters[i] for i in d] for d in data]
        expected = [(np.any(d), np.all(d)) for d in data]

        for n, params in enumerate(data_parameters):
            for m, agg_func in enumerate(["any", "all"]):
                p = AggregatedIndexParameter(model, params, agg_func=agg_func)
                e = np.ones([len(model.timestepper), num_comb]) * expected[n][m]
                r = AssertionRecorder(model, p, expected_data=e, name="assertion {}-{}".format(n, agg_func))

        model.run()
Example #2
0
def test_two_scenarios(simple_linear_model, ):
    """Basic test of Scenario functionality"""
    model = simple_linear_model  # Convenience renaming

    scenario_input = Scenario(model, 'Inflow', size=2)
    model.nodes["Input"].max_flow = ConstantScenarioParameter(
        scenario_input, [5.0, 10.0])

    scenario_outflow = Scenario(model, 'Outflow', size=2)
    model.nodes["Output"].max_flow = ConstantScenarioParameter(
        scenario_outflow, [3.0, 8.0])
    model.nodes["Output"].cost = -2.0

    # add numpy recorders to input and output nodes
    NumpyArrayNodeRecorder(model, model.nodes["Input"], "input")
    NumpyArrayNodeRecorder(model, model.nodes["Output"], "output")

    expected_node_results = {
        "Input": [3.0, 5.0, 3.0, 8.0],
        "Link": [3.0, 5.0, 3.0, 8.0],
        "Output": [3.0, 5.0, 3.0, 8.0],
    }

    assert_model(model, expected_node_results)

    model.run()

    # combine recorder outputs to a single dataframe
    df = model.to_dataframe()
    assert (df.shape == (365, 2 * 2 * 2))
    assert_allclose(df["input", 0, 0].iloc[0], 3.0)
    assert_allclose(df["input", 0, 1].iloc[0], 5.0)
    assert_allclose(df["input", 1, 0].iloc[0], 3.0)
    assert_allclose(df["input", 1, 1].iloc[0], 8.0)
Example #3
0
def test_parameter_array_indexed_scenario_monthly_factors(simple_linear_model):
    """
    Test ArrayIndexedParameterScenarioMonthlyFactors

    """
    model = simple_linear_model
    # Baseline timeseries data
    values = np.arange(len(model.timestepper), dtype=np.float64)

    # Add two scenarios
    scA = Scenario(model, 'Scenario A', size=2)
    scB = Scenario(model, 'Scenario B', size=5)

    # Random factors for each Scenario B value per month
    factors = np.random.rand(scB.size, 12)

    p = ArrayIndexedScenarioMonthlyFactorsParameter(model, scB, values, factors)
    model.setup()

    # Iterate in time
    for v, ts in zip(values, model.timestepper):
        imth = ts.datetime.month - 1
        # Now ensure the appropriate value is returned for the Scenario B indices.
        for i, (a, b) in enumerate(itertools.product(range(scA.size), range(scB.size))):
            f = factors[b, imth]
            si = ScenarioIndex(i, np.array([a, b], dtype=np.int32))
            np.testing.assert_allclose(p.value(ts, si), v*f)
Example #4
0
def test_parameter_array_indexed_scenario_monthly_factors_json(model):
    model.path = os.path.join(TEST_DIR, "models")
    scA = Scenario(model, 'Scenario A', size=2)
    scB = Scenario(model, 'Scenario B', size=3)

    p1 = ArrayIndexedScenarioMonthlyFactorsParameter.load(model, {
        "scenario": "Scenario A",
        "values": list(range(32)),
        "factors": [list(range(1, 13)),list(range(13, 25))],
    })

    p2 = ArrayIndexedScenarioMonthlyFactorsParameter.load(model, {
        "scenario": "Scenario B",
        "values": {
            "url": "timeseries1.csv",
            "index_col": "Timestamp",
            "column": "Data",
        },
        "factors": {
            "url": "monthly_profiles.csv",
            "index_col": "scenario",
        },
    })

    node1 = Input(model, "node1", max_flow=p1)
    node2 = Input(model, "node2", max_flow=p2)
    nodeN = Output(model, "nodeN", max_flow=None, cost=-1)
    node1.connect(nodeN)
    node2.connect(nodeN)

    model.timestepper.start = "2015-01-01"
    model.timestepper.end = "2015-01-31"
    model.run()
Example #5
0
def test_parameter_df_upsampling_multiple_columns(model):
    """ Test that the `DataFrameParameter` works with multiple columns that map to a `Scenario`
    """
    scA = Scenario(model, 'A', size=20)
    scB = Scenario(model, 'B', size=2)
    # scenario indices (not used for this test)

    # Use a 7 day timestep for this test and run 2015
    model.timestepper.delta = datetime.timedelta(7)
    model.timestepper.start = pd.to_datetime('2015-01-01')
    model.timestepper.end = pd.to_datetime('2015-12-31')

    # Daily time-step
    index = pd.date_range('2015-01-01', periods=365, freq='D')
    df = pd.DataFrame(np.random.rand(365, 20), index=index)

    p = DataFrameParameter(model, df, scenario=scA)
    p.setup()

    A = df.resample('7D', axis=0).mean()
    for v, ts in zip(A.values, model.timestepper):
        np.testing.assert_allclose([
            p.value(ts, ScenarioIndex(i, np.array([i], dtype=np.int32)))
            for i in range(20)
        ], v)

    p = DataFrameParameter(model, df, scenario=scB)
    with pytest.raises(ValueError):
        p.setup()
Example #6
0
def test_scenario_collection():
    """ Basic test of Scenario and ScenarioCollection API """

    model = Model()

    # There is 1 combination when there are no Scenarios
    model.scenarios.setup()
    assert(len(model.scenarios.combinations) == 1)
    assert(len(model.scenarios) == 0)
    scA = Scenario(model, 'Scenario A', size=3)
    model.scenarios.setup()
    assert(len(model.scenarios.combinations) == 3)
    assert(len(model.scenarios) == 1)
    scA = Scenario(model, 'Scenario B', size=2)
    model.scenarios.setup()
    assert(len(model.scenarios.combinations) == 6)
    assert(len(model.scenarios) == 2)

    assert_equal([comb.indices for comb in model.scenarios.combinations],
                 [[0, 0], [0, 1], [1, 0], [1, 1], [2, 0], [2, 1]])

    names = model.scenarios.combination_names
    for n, (ia, ib) in zip(names, [[0, 0], [0, 1], [1, 0], [1, 1], [2, 0], [2, 1]]):
        assert n == 'Scenario A.{:03d}-Scenario B.{:03d}'.format(ia, ib)

    index = model.scenarios.multiindex
    assert_equal(index.tolist(),
                 [[0, 0], [0, 1], [1, 0], [1, 1], [2, 0], [2, 1]])
    assert_equal(index.names, ['Scenario A', 'Scenario B'])
Example #7
0
def test_dirty_scenario(simple_linear_model):
    """Adding a scenario to a model makes it dirty"""
    model = simple_linear_model
    model.setup()
    assert(not model.dirty)
    scenario = Scenario(model, "test", size=42)
    assert(model.dirty)
Example #8
0
def test_transfer(pywr_solver, size):
    """Test a simple transfer model. """

    model = Model()

    Scenario(model, name='test', size=size)

    supply1 = Input(model, name='supply-1', max_flow=5.0)
    wtw1 = Link(model, name='wtw-1')
    demand1 = Output(model, name='demand-1', max_flow=10.0, cost=-10.0)

    supply1.connect(wtw1)
    wtw1.connect(demand1)

    supply2 = Input(model, name='supply-2', max_flow=15.0)
    wtw2 = Link(model, name='wtw-2')
    demand2 = Output(model, name='demand-2', max_flow=10.0, cost=-10.0)

    supply2.connect(wtw2)
    wtw2.connect(demand2)

    transfer21 = Link(model, name='transfer-12', max_flow=2.0, cost=1.0)
    wtw2.connect(transfer21)
    transfer21.connect(wtw1)

    model.setup()
    model.step()

    assert_allclose(supply1.flow, [5.0] * size)
    assert_allclose(demand1.flow, [7.0] * size)
    assert_allclose(supply2.flow, [12.0] * size)
    assert_allclose(demand2.flow, [10.0] * size)
    assert_allclose(transfer21.flow, [2.0] * size)
Example #9
0
def test_aggregated_storage_scenarios(three_storage_model):
    """ Test `AggregatedScenario` correctly sums over scenarios. """
    from pywr.core import Scenario
    from pywr.parameters import ConstantScenarioParameter
    m = three_storage_model
    sc = Scenario(m, 'A', size=5)

    agg_stg = m.nodes['Total Storage']
    stgs = [m.nodes['Storage {}'.format(num)] for num in range(3)]
    # Setup scenario
    inpt1 = m.nodes['Input 1'].max_flow = ConstantScenarioParameter(
        sc, range(sc.size))

    m.setup()
    m.step()

    # Finally check volume is summed correctly
    np.testing.assert_allclose(agg_stg.volume, np.sum(s.volume for s in stgs))
    current_pc = np.sum(s.volume for s in stgs) / (np.sum(s.max_volume
                                                          for s in stgs))
    np.testing.assert_allclose(agg_stg.current_pc, current_pc)
    np.testing.assert_allclose(agg_stg.flow, np.sum(s.flow for s in stgs))

    m.step()

    # Finally check volume is summed correctly
    np.testing.assert_allclose(agg_stg.volume, np.sum(s.volume for s in stgs))
    current_pc = np.sum(s.volume for s in stgs) / (np.sum(s.max_volume
                                                          for s in stgs))
    np.testing.assert_allclose(agg_stg.current_pc, current_pc)
    np.testing.assert_allclose(agg_stg.flow, np.sum(s.flow for s in stgs))
Example #10
0
def test_delay_node(key, delay, initial_flow):
    """Test that the `DelayNode` and the `FlowDelayParameter` internal to it correctly delay node for a range of inputs and
    across scenarios"""
    model = Model()

    model.timestepper.start = "2015/01/01"
    model.timestepper.end = "2015/01/31"

    scen = Scenario(model, name="scenario", size=2)
    flow_vals = np.arange(1, 63).reshape((31, 2), order="F")
    flow = ArrayIndexedScenarioParameter(model, scen, flow_vals)

    catchment = Catchment(model, name="input", flow=flow)
    kwargs = {key: delay}
    if initial_flow:
        kwargs["initial_flow"] = initial_flow
    delaynode = DelayNode(model, name="delaynode", **kwargs)
    output = Output(model, name="output")

    catchment.connect(delaynode)
    delaynode.connect(output)

    rec = NumpyArrayNodeRecorder(model, output)

    model.run()
    if initial_flow:
        expected = np.concatenate(
            [np.full((delay, 2), initial_flow), flow_vals[:-delay, :]])
    else:
        expected = np.concatenate(
            [np.zeros((delay, 2)), flow_vals[:-delay, :]])

    assert_array_almost_equal(rec.data, expected)
Example #11
0
def test_mean_flow_recorder(solver):
    model = Model(solver=solver)
    model.timestepper.start = pandas.to_datetime("2016-01-01")
    model.timestepper.end = pandas.to_datetime("2016-01-04")

    inpt = Input(model, "input")
    otpt = Output(model, "output")
    inpt.connect(otpt)

    rec_flow = NumpyArrayNodeRecorder(model, inpt)
    rec_mean = MeanFlowRecorder(model, node=inpt, timesteps=3)

    scenario = Scenario(model, "dummy", size=2)

    inpt.max_flow = inpt.min_flow = FunctionParameter(model, inpt, lambda model, t, si: 2 + t.index)
    model.run()

    expected = [
        2.0,
        (2.0 + 3.0) / 2,
        (2.0 + 3.0 + 4.0) / 3,
        (3.0 + 4.0 + 5.0) / 3,  # zeroth day forgotten
    ]

    for value, expected_value in zip(rec_mean.data[:, 0], expected):
        assert_allclose(value, expected_value)
Example #12
0
def test_annual_count_index_parameter_recorder(simple_storage_model):
    """ Test AnnualCountIndexParameterRecord

    The test sets uses a simple reservoir model with different inputs that
    trigger a control curve failure after different numbers of years.
    """
    from pywr.parameters import ConstantScenarioParameter, ConstantParameter
    from pywr.parameters.control_curves import ControlCurveIndexParameter
    model = simple_storage_model
    scenario = Scenario(model, 'A', size=2)
    # Simulate 5 years
    model.timestepper.start = '2015-01-01'
    model.timestepper.end = '2019-12-31'
    # Control curve parameter
    param = ControlCurveIndexParameter(model, model.nodes['Storage'], ConstantParameter(model, 0.25))

    # Storage model has a capacity of 20, but starts at 10 Ml
    # Demand is roughly 2 Ml/d per year
    #  First ensemble balances the demand
    #  Second ensemble should fail during 3rd year
    demand = 2.0 / 365
    model.nodes['Input'].max_flow = ConstantScenarioParameter(model, scenario, [demand, 0])
    model.nodes['Output'].max_flow = demand

    # Create the recorder with a threshold of 1
    rec = AnnualCountIndexParameterRecorder(model, param, 1)

    model.run()
    # We expect no failures in the first ensemble, but 3 out of 5 in the second
    assert_allclose(rec.values(), [0, 3])
Example #13
0
def test_scenario_storage():
    """Test the behaviour of Storage nodes with multiple scenarios

    The model defined has two inflow scenarios: 5 and 10. It is expected that
    the volume in the storage node should increase at different rates in the
    two scenarios.
    """
    model = Model()

    i = Input(model, 'input', max_flow=999)
    s = Storage(model, 'storage', num_inputs=1, num_outputs=1, max_volume=1000, initial_volume=500)
    o = Output(model, 'output', max_flow=999)

    scenario_input = Scenario(model, 'Inflow', size=2)
    i.min_flow = ConstantScenarioParameter(model, scenario_input, [5.0, 10.0])

    i.connect(s)
    s.connect(o)

    s_rec = NumpyArrayStorageRecorder(model, s)

    model.run()

    assert_allclose(i.flow, [5, 10])
    assert_allclose(s_rec.data[0], [505, 510])
    assert_allclose(s_rec.data[1], [510, 520])
Example #14
0
def test_transfer2(pywr_solver, size):
    """Test a simple transfer model. """

    model = Model()

    Scenario(model, name='test', size=size)

    demands = [9.47, 7.65, 9.04, 9.56, 9.44]
    supply = [4.74, 6.59, 12.04, 8.81, 11.75]

    for i, (s, d) in enumerate(zip(supply, demands)):
        s = Input(model, name=f'supply-{i}', max_flow=s)
        lnk = Link(model, name=f'wtw-{i}')
        d = Output(model, name=f'demand-{i}', max_flow=d, cost=-10.0)

        s.connect(lnk)
        lnk.connect(d)

    transfer04 = Link(model, name='transfer-04', max_flow=15.36, cost=1.0)

    model.nodes['wtw-0'].connect(transfer04)
    transfer04.connect(model.nodes['wtw-4'])

    model.setup()
    model.step()

    expected_supply = [4.74, 6.59, 9.04, 8.81, 9.44]

    for i, expected in enumerate(expected_supply):
        assert_allclose(model.nodes[f'supply-{i}'].flow, [expected] * size)

    assert_allclose(transfer04.flow, [0.0] * size, atol=1e-8)
Example #15
0
def test_parameter_constant_scenario(simple_linear_model):
    """
    Test ConstantScenarioParameter

    """
    model = simple_linear_model
    # Add two scenarios
    scA = Scenario(model, 'Scenario A', size=2)
    scB = Scenario(model, 'Scenario B', size=5)

    p = ConstantScenarioParameter(model, scB, np.arange(scB.size, dtype=np.float64))
    model.setup()
    ts = model.timestepper.current
    # Now ensure the appropriate value is returned for the Scenario B indices.
    for i, (a, b) in enumerate(itertools.product(range(scA.size), range(scB.size))):
        si = ScenarioIndex(i, np.array([a, b], dtype=np.int32))
        np.testing.assert_allclose(p.value(ts, si), float(b))
Example #16
0
def test_ocptt(simple_linear_model):
    model = simple_linear_model
    inpt = model.nodes["Input"]
    s1 = Scenario(model, "scenario 1", size=3)
    s2 = Scenario(model, "scenario 1", size=2)
    x = np.arange(len(model.timestepper)).reshape([len(model.timestepper), 1]) + 5
    y = np.arange(s1.size).reshape([1, s1.size])
    z = x * y ** 2
    p = ArrayIndexedScenarioParameter(model, s1, z)
    inpt.max_flow = p
    model.setup()
    model.reset()
    model.step()

    values1 = [p.get_value(scenario_index) for scenario_index in model.scenarios.combinations]
    values2 = list(p.get_all_values())
    assert_allclose(values1, [0, 0, 5, 5, 20, 20])
    assert_allclose(values2, [0, 0, 5, 5, 20, 20])
Example #17
0
    def test_basic_use(self, simple_linear_model):
        """ Test the basic use of `ConstantParameter` using the Python API """
        model = simple_linear_model
        # Add two scenarios
        scA = Scenario(model, 'Scenario A', size=2)
        scB = Scenario(model, 'Scenario B', size=5)

        p = ConstantParameter(model, np.pi, name='pi', comment='Mmmmm Pi!')

        assert not p.is_variable
        assert p.double_size == 1
        assert p.integer_size == 0

        model.setup()
        ts = model.timestepper.current
        # Now ensure the appropriate value is returned for all scenarios
        for i, (a, b) in enumerate(itertools.product(range(scA.size), range(scB.size))):
            si = ScenarioIndex(i, np.array([a, b], dtype=np.int32))
            np.testing.assert_allclose(p.value(ts, si), np.pi)
Example #18
0
def test_two_scenarios(simple_linear_model, ):
    """Basic test of Scenario functionality"""
    model = simple_linear_model  # Convenience renaming

    scenario_input = Scenario(model, 'Inflow', size=2)
    model.nodes["Input"].max_flow = ConstantScenarioParameter(
        model, scenario_input, [5.0, 10.0])

    scenario_outflow = Scenario(model,
                                'Outflow',
                                size=2,
                                ensemble_names=['High', 'Low'])
    model.nodes["Output"].max_flow = ConstantScenarioParameter(
        model, scenario_outflow, [3.0, 8.0])
    model.nodes["Output"].cost = -2.0

    # Check ensemble names are provided in the multi-index
    index = model.scenarios.multiindex
    assert index.levels[0].name == 'Inflow'
    assert index.levels[1].name == 'Outflow'
    assert np.all(index.levels[1] == ['High', 'Low'])

    # add numpy recorders to input and output nodes
    NumpyArrayNodeRecorder(model, model.nodes["Input"], "input")
    NumpyArrayNodeRecorder(model, model.nodes["Output"], "output")

    expected_node_results = {
        "Input": [3.0, 5.0, 3.0, 8.0],
        "Link": [3.0, 5.0, 3.0, 8.0],
        "Output": [3.0, 5.0, 3.0, 8.0],
    }

    assert_model(model, expected_node_results)

    model.run()

    # combine recorder outputs to a single dataframe
    df = model.to_dataframe()
    assert (df.shape == (365, 2 * 2 * 2))
    assert_allclose(df["input", 0, 'High'].iloc[0], 3.0)
    assert_allclose(df["input", 0, 'Low'].iloc[0], 5.0)
    assert_allclose(df["input", 1, 'High'].iloc[0], 3.0)
    assert_allclose(df["input", 1, 'Low'].iloc[0], 8.0)
Example #19
0
def test_threshold_parameter(simple_linear_model):
    model = simple_linear_model
    model.timestepper.delta = 150

    scenario = Scenario(model, "Scenario", size=2)

    class DummyRecorder(Recorder):
        def __init__(self, model, value, *args, **kwargs):
            super(DummyRecorder, self).__init__(model, *args, **kwargs)
            self.val = value

        def setup(self):
            super(DummyRecorder, self).setup()
            num_comb = len(model.scenarios.combinations)
            self.data = np.empty([len(model.timestepper), num_comb],
                                 dtype=np.float64)

        def after(self):
            timestep = model.timestepper.current
            self.data[timestep.index, :] = self.val

    threshold = 10.0
    values = [50.0, 60.0]

    rec1 = DummyRecorder(model, threshold - 5, name="rec1")  # below
    rec2 = DummyRecorder(model, threshold, name="rec2")  # equal
    rec3 = DummyRecorder(model, threshold + 5, name="rec3")  # above

    expected = [
        ("LT", (1, 0, 0)),
        ("GT", (0, 0, 1)),
        ("EQ", (0, 1, 0)),
        ("LE", (1, 1, 0)),
        ("GE", (0, 1, 1)),
    ]

    for predicate, (value_lt, value_eq, value_gt) in expected:
        for rec in (rec1, rec2, rec3):
            param = RecorderThresholdParameter(model,
                                               rec,
                                               threshold,
                                               values=values,
                                               predicate=predicate)
            e_val = values[getattr(rec.val, "__{}__".format(
                predicate.lower()))(threshold)]
            e = np.ones([
                len(model.timestepper),
                len(model.scenarios.get_combinations())
            ]) * e_val
            e[0, :] = values[1]  # first timestep is always "on"
            r = AssertionRecorder(model, param, expected_data=e)
            r.name = "assert {} {} {}".format(rec.val, predicate, threshold)

    model.run()
Example #20
0
    def test_min(self, model):
        # Add two scenarios
        scA = Scenario(model, 'Scenario A', size=2)
        scB = Scenario(model, 'Scenario B', size=5)

        values = np.arange(366, dtype=np.float64)
        p1 = DailyProfileParameter(values)
        p2 = ConstantScenarioParameter(scB,
                                       np.arange(scB.size, dtype=np.float64))

        p = AggregatedParameter([
            p1,
        ], agg_func='min')
        p.add(p2)

        p.setup(model)
        for ts in model.timestepper:
            iday = ts.datetime.dayofyear - 1
            for i in range(scB.size):
                si = ScenarioIndex(i, np.array([0, i], dtype=np.int32))
                np.testing.assert_allclose(p.value(ts, si),
                                           min(values[iday], i))
Example #21
0
    def test_max(self, model):
        # Add two scenarios
        scA = Scenario(model, 'Scenario A', size=2)
        scB = Scenario(model, 'Scenario B', size=5)

        values = np.arange(366, dtype=np.float64)
        p1 = DailyProfileParameter(values)
        p2 = ConstantScenarioParameter(scB,
                                       np.arange(scB.size, dtype=np.float64))

        p = AggregatedParameter([p1, p2], agg_func='max')
        p.setup(model)

        for ts in model.timestepper:
            month = ts.datetime.month
            day = ts.datetime.day
            iday = int((datetime.datetime(2016, month, day) -
                        datetime.datetime(2016, 1, 1)).days)
            for i in range(scB.size):
                si = ScenarioIndex(i, np.array([0, i], dtype=np.int32))
                np.testing.assert_allclose(p.value(ts, si),
                                           max(values[iday], i))
Example #22
0
    def test_agg(self, simple_linear_model, agg_func):
        model = simple_linear_model
        model.timestepper.delta = 15

        scenarioA = Scenario(model, "Scenario A", size=2)
        scenarioB = Scenario(model, "Scenario B", size=5)

        values = np.arange(366, dtype=np.float64)
        p1 = DailyProfileParameter(model, values)
        p2 = ConstantScenarioParameter(model, scenarioB, np.arange(scenarioB.size, dtype=np.float64))

        p = AggregatedParameter(model, [p1, p2], agg_func=agg_func)

        func = TestAggregatedParameter.funcs[agg_func]

        @assert_rec(model, p)
        def expected_func(timestep, scenario_index):
            x = p1.get_value(scenario_index)
            y = p2.get_value(scenario_index)
            return func(np.array([x,y]))

        model.run()
Example #23
0
def test_scenario_user_combinations(simple_linear_model):
    model = simple_linear_model

    # create two scenarios
    s1 = Scenario(model=model, name="A", size=20)
    s2 = Scenario(model=model, name="B", size=3)

    model.scenarios.user_combinations = [[0, 1], [1, 1]]
    combinations = model.scenarios.get_combinations()
    assert(len(combinations) == 2)
    # ScenarioCollection.shape is simply the number of combinations
    assert model.scenarios.shape == (2, )

    # Test wrong number of dimensions
    with pytest.raises(ValueError):
        model.scenarios.user_combinations = [0, 1, 1, 1]

    # Test out of range index
    with pytest.raises(ValueError):
        model.scenarios.user_combinations = [[19, 3], [2, 2]]
    with pytest.raises(ValueError):
        model.scenarios.user_combinations = [[-1, 2], [2, 2]]
Example #24
0
    def test_init(self, model):
        scenario = Scenario(model, 'A', 10)
        values = np.random.rand(10, 12)

        p = ScenarioMonthlyProfileParameter(scenario, values)

        p.setup(model)
        # Iterate in time
        for ts in model.timestepper:
            imth = ts.datetime.month - 1
            for i in range(scenario.size):
                si = ScenarioIndex(i, np.array([i], dtype=np.int32))
                np.testing.assert_allclose(p.value(ts, si), values[i, imth])
Example #25
0
    def test_user_scenarios(self, simple_linear_model, tmpdir):
        """
        Test the TablesRecorder with user defined scenario subset

        """
        from pywr.parameters import ConstantScenarioParameter
        model = simple_linear_model
        scA = Scenario(model, name='A', size=4)
        scB = Scenario(model, name='B', size=2)

        # Use first and last combinations
        model.scenarios.user_combinations = [[0, 0], [3, 1]]

        otpt = model.nodes['Output']
        inpt = model.nodes['Input']

        inpt.max_flow = ConstantScenarioParameter(model, scA, [10, 20, 30, 40])
        otpt.max_flow = ConstantScenarioParameter(model, scB, [20, 40])
        otpt.cost = -2.0

        h5file = tmpdir.join('output.h5')
        import tables
        with tables.open_file(str(h5file), 'w') as h5f:
            rec = TablesRecorder(model, h5f)

            model.run()

            for node_name in model.nodes.keys():
                ca = h5f.get_node('/', node_name)
                assert ca.shape == (365, 2)
                np.testing.assert_allclose(ca[0, ...], [10, 40])

            # check combinations table exists
            combinations = h5f.get_node('/scenario_combinations')
            for i, comb in enumerate(model.scenarios.user_combinations):
                row = combinations[i]
                assert row['A'] == comb[0]
                assert row['B'] == comb[1]
Example #26
0
def test_concatenated_dataframes(simple_storage_model):
    """
    Test that Model.to_dataframe returns something sensible.

    """
    model = simple_storage_model

    scA = Scenario(model, 'A', size=2)
    scB = Scenario(model, 'B', size=3)

    res = model.nodes['Storage']
    rec1 = NumpyArrayStorageRecorder(model, res)
    otpt = model.nodes['Output']
    rec2 = NumpyArrayNodeRecorder(model, otpt)
    # The following can't return a DataFrame; is included to check
    # it doesn't cause any issues
    rec3 = TotalDeficitNodeRecorder(model, otpt)

    model.run()

    df = model.to_dataframe()
    assert df.shape == (5, 2*2*3)
    assert df.columns.names == ['Recorder', 'A', 'B']
Example #27
0
def test_cache_scenarios(simple_model):
    """
    Test caching across scenarios.
    """
    model = simple_model
    scen = Scenario(model, 'Scenario A', size=2)

    param = ConstantScenarioParameter(scen, [10, 20])

    inpt = model.nodes["input"]
    inpt.max_flow = CachedParameter(param)

    model.run()
    assert_allclose(inpt.flow, [10.0, 20.0])
Example #28
0
    def test_agg(self, simple_linear_model, agg_func):
        model = simple_linear_model
        model.timestepper.delta = 1
        model.timestepper.start = "2017-01-01"
        model.timestepper.end = "2017-01-03"

        scenarioA = Scenario(model, "Scenario A", size=2)
        scenarioB = Scenario(model, "Scenario B", size=5)

        p1 = DummyIndexParameter(model, 2)
        p2 = DummyIndexParameter(model, 3)

        p = AggregatedIndexParameter(model, [p1, p2], agg_func=agg_func)

        func = TestAggregatedIndexParameter.funcs[agg_func]

        @assert_rec(model, p)
        def expected_func(timestep, scenario_index):
            x = p1.get_index(scenario_index)
            y = p2.get_index(scenario_index)
            return func(np.array([x, y], np.int32))

        model.run()
Example #29
0
def cyclical_storage_model(simple_storage_model):
    """ Extends simple_storage_model to have a cyclical boundary condition """
    from pywr.parameters import AnnualHarmonicSeriesParameter, ConstantScenarioParameter
    m = simple_storage_model
    s = Scenario(m, name='Scenario A', size=3)

    m.timestepper.end = '2017-12-31'
    m.timestepper.delta = 5

    inpt = m.nodes['Input']
    inpt.max_flow = AnnualHarmonicSeriesParameter(m, 5, [0.1, 0.0, 0.25], [0.0, 0.0, 0.0])

    otpt = m.nodes['Output']
    otpt.max_flow = ConstantScenarioParameter(m, s, [5, 6, 2])

    return m
Example #30
0
def test_scenario_slices(simple_linear_model):
    """Test slicing of scenarios"""
    model = simple_linear_model

    # create two scenarios
    s1 = Scenario(model=model, name="A", size=20)
    s2 = Scenario(model=model, name="B", size=3)

    combinations = model.scenarios.get_combinations()
    assert(len(combinations) == 20 * 3)

    s1.slice = slice(0, None, 2)
    combinations = model.scenarios.get_combinations()
    assert(len(combinations) == 10 * 3)

    # check multiindex respects scenario slices
    index = model.scenarios.multiindex
    assert(len(index.levels) == 2)
    assert(len(index.levels[0]) == 10)
    assert(len(index.levels[1]) == 3)
    assert(len(index.codes) == 2)
    assert(len(index.codes[0]) == 10 * 3)
    assert(len(index.codes[1]) == 10 * 3)
    assert(index.names == ["A", "B"])

    s2.slice = slice(1, 3, 1)
    combinations = model.scenarios.get_combinations()
    assert(len(combinations) == 10 * 2)

    assert(combinations[0].global_id == 0)
    assert(tuple(combinations[0].indices) == (0, 1))

    assert(combinations[-1].global_id == 19)
    assert(tuple(combinations[-1].indices) == (18, 2))

    model.run()

    node = model.nodes["Input"]
    assert((len(combinations),) == node.flow.shape)

    s1.slice = None
    s2.slice = None
    combinations = model.scenarios.get_combinations()
    assert(len(combinations) == 20 * 3)