def test_agg_func_get_set(self, model, agg_func): if agg_func == "custom": agg_func = custom_test_func p = AggregatedParameter(model, [], agg_func=agg_func) assert p.agg_func == agg_func p.agg_func = "product" assert p.agg_func == "product"
def test_storage_max_volume_param_raises(solver): """Test a that an max_volume with a Parameter that has children is an error """ model = Model(solver=solver, start=pandas.to_datetime('2016-01-01'), end=pandas.to_datetime('2016-01-01')) storage = Storage(model, 'storage', num_inputs=1, num_outputs=0) otpt = Output(model, 'output', max_flow=99999, cost=-99999) storage.connect(otpt) p = AggregatedParameter( model, [ConstantParameter(model, 20.0), ConstantParameter(model, 20.0)], agg_func='sum') p1 = AggregatedParameter(model, [p, ConstantParameter(model, 1.5)], agg_func="product") storage.max_volume = p1 storage.initial_volume = 10.0 with pytest.raises(RuntimeError): model.run()
def _make_weather_nodes(self, model, weather, cost): if not isinstance(self.area, Parameter): raise ValueError( 'Weather nodes can only be created if an area Parameter is given.' ) rainfall = weather['rainfall'].astype(np.float64) rainfall_param = MonthlyProfileParameter(model, rainfall) evaporation = weather['evaporation'].astype(np.float64) evaporation_param = MonthlyProfileParameter(model, evaporation) # Assume rainfall/evap is mm/day # Need to convert: # Mm2 -> m2 # mm/day -> m/day # m3/day -> Mm3/day # TODO allow this to be configured const = ConstantParameter(model, 1e6 * 1e-3 * 1e-6) # Create the flow parameters multiplying area by rate of rainfall/evap rainfall_flow_param = AggregatedParameter( model, [rainfall_param, const, self.area], agg_func='product') evaporation_flow_param = AggregatedParameter( model, [evaporation_param, const, self.area], agg_func='product') # Create the nodes to provide the flows rainfall_node = Input(model, '{}.rainfall'.format(self.name), parent=self) rainfall_node.max_flow = rainfall_flow_param rainfall_node.cost = cost evporation_node = Output(model, '{}.evaporation'.format(self.name), parent=self) evporation_node.max_flow = evaporation_flow_param evporation_node.cost = cost rainfall_node.connect(self) self.connect(evporation_node) self.rainfall_node = rainfall_node self.evaporation_node = evporation_node # Finally record these flows self.rainfall_recorder = NumpyArrayNodeRecorder( model, rainfall_node, name=f'__{rainfall_node.name}__:rainfall') self.evaporation_recorder = NumpyArrayNodeRecorder( model, evporation_node, name=f'__{evporation_node.name}__:evaporation')
def test_storage_max_volume_param_raises(solver): """Test a that an max_volume with a Parameter that has children. Only some aggregated style parameters should work here. """ model = Model(solver=solver, start=pandas.to_datetime('2016-01-01'), end=pandas.to_datetime('2016-01-01')) storage = Storage(model, 'storage', num_inputs=1, num_outputs=0) otpt = Output(model, 'output', max_flow=99999, cost=-99999) storage.connect(otpt) p = AggregatedParameter( model, [ConstantParameter(model, 20.0), ConstantParameter(model, 20.0)], agg_func='sum') storage.max_volume = p storage.initial_volume = 10.0 model.setup() np.testing.assert_allclose(storage.current_pc, 0.25)
def __init__(self, model, name, *args, **kwargs): demand = kwargs.pop('demand', ConstantParameter(model, 0)) supply = kwargs.pop('supply', ConstantParameter(model, 0)) headroom = kwargs.pop('headroom', ConstantParameter(model, 0)) super().__init__(model, name, *args, **kwargs) self.supply_node = Input(model, name=f'{name}-supply', parent=self) self.demand_node = Output(model, name=f'{name}-demand', parent=self) self.supply_node.max_flow = MaxParameter(model, supply) demand_headroom = AggregatedParameter(model, parameters=[demand, headroom], agg_func='sum') self.demand_node.max_flow = MaxParameter(model, demand_headroom) self.demand_node.cost = -100 self.supply_node.connect(self) self.connect(self.demand_node) # Track deficits deficit_param = DeficitParameter(model, self.demand_node, name=f'{name}-deficit_param') NumpyArrayParameterRecorder(model, deficit_param, name=f'__{name}-demand__:deficit', temporal_agg_func='sum')
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))
def _make_rainfall_node(self, model, rainfall, cost): if not isinstance(self.area, Parameter): log.warning( 'Weather nodes can only be created if an area Parameter is given.' ) return if rainfall is None: try: rainfall_param = load_parameter(model, f'__{self.name}__:rainfall') except KeyError: log.warning( f"Please speficy a rainfall or a weather on node {self.name}" ) return elif isinstance(rainfall, pd.DataFrame) or isinstance( rainfall, pd.Series): #assume it's a dataframe rainfall = rainfall.astype(np.float64) rainfall_param = MonthlyProfileParameter(model, rainfall) else: rainfall_param = rainfall # Create the flow parameters multiplying area by rate of rainfall/evap rainfall_flow_param = AggregatedParameter( model, [rainfall_param, self.const, self.area], agg_func='product') # Create the nodes to provide the flows rainfall_node = Input(model, '{}.rainfall'.format(self.name), parent=self) rainfall_node.max_flow = rainfall_flow_param rainfall_node.cost = cost rainfall_node.connect(self) self.rainfall_node = rainfall_node # Finally record these flows self.rainfall_recorder = NumpyArrayNodeRecorder( model, rainfall_node, name=f'__{rainfall_node.name}__:rainfall')
def test_storage_max_volume_nested_param(): """Test that a max_volume can be used with a Parameter with children. """ model = Model( start=pandas.to_datetime('2016-01-01'), end=pandas.to_datetime('2016-01-01') ) storage = Storage(model, 'storage', num_inputs=1, num_outputs=0) otpt = Output(model, 'output', max_flow=99999, cost=-99999) storage.connect(otpt) p = AggregatedParameter(model, [ConstantParameter(model, 20.0), ConstantParameter(model, 20.0)], agg_func='sum') storage.max_volume = p storage.initial_volume = 10.0 model.setup() np.testing.assert_allclose(storage.current_pc, 0.25)
def _make_evaporation_node(self, model, evaporation, cost): if not isinstance(self.area, Parameter): log.warning( 'Evaporation nodes can only be created if an area Parameter is given.' ) return if evaporation is None: try: evaporation_param = load_parameter( model, f'__{self.name}__:evaporation') except KeyError: log.warning( f"Please speficy an evaporation or a weather on node {self.name}" ) return elif isinstance(evaporation, pd.DataFrame) or isinstance( evaporation, pd.Series): evaporation = evaporation.astype(np.float64) evaporation_param = MonthlyProfileParameter(model, evaporation) else: evaporation_param = evaporation evaporation_flow_param = AggregatedParameter( model, [evaporation_param, self.const, self.area], agg_func='product') evporation_node = Output(model, '{}.evaporation'.format(self.name), parent=self) evporation_node.max_flow = evaporation_flow_param evporation_node.cost = cost self.connect(evporation_node) self.evaporation_node = evporation_node self.evaporation_recorder = NumpyArrayNodeRecorder( model, evporation_node, name=f'__{evporation_node.name}__:evaporation')
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()
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))